2012-10-21 22 views
10

Sto cercando di scaricare il file xls per un sito Web. Quando clicco sul link per scaricare il file, ottengo una casella di conferma javascript. Lo gestisco come sottoScarica file utilizzando HtmlUnit

ConfirmHandler okHandler = new ConfirmHandler(){ 
      public boolean handleConfirm(Page page, String message) { 
       return true; 
      } 
     }; 
    webClient.setConfirmHandler(okHandler); 

C'è un collegamento per scaricare il file.

<a href="./my_file.php?mode=xls&amp;w=d2hlcmUgc2VsbElkPSd3b3JsZGNvbScgYW5kIHN0YXR1cz0nV0FJVERFTEknIGFuZCBkYXRlIDw9IC0xMzQ4MTUzMjAwICBhbmQgZGF0ZSA%2BPSAtMTM1MDgzMTU5OSA%3D" target="actionFrame" onclick="return confirm('Do you want do download XLS file?')"><u>Download</u></a> 

clicco sul collegamento con il metodo

HTMLPage x = webClient.getPage("http://working.com/download"); 
HtmlAnchor anchor = (HtmlAnchor) x.getFirstByXPath("//a[@target='actionFrame']"); 
anchor.click(); 

handeConfirm() è excuted. Ma non ho idea di come salvare il flusso di file dal server. Ho provato a vedere il flusso con il codice qui sotto.

anchor.click().getWebResponse().getContentAsString(); 

Ma il risultato è lo stesso della pagina x. Qualcuno sa come catturare il flusso dal server? Grazie.

+0

'anchor.click()' restituirà una pagina. Questo dovrebbe contian il tuo file XLS – Lee

+0

vedere la mia risposta a una domanda simile a http://stackoverflow.com/a/28471835/612123 – culmat

risposta

7

Ho trovato un modo per ottenere InputStream utilizzando WebWindowListener. All'interno di webWindowContentChanged (evento WebWindowEvent), inserisco il codice qui sotto.

InputStream xls = event.getWebWindow().getEnclosedPage().getWebResponse().getContentAsStream(); 

Dopo aver ricevuto xls, è possibile salvare il file nel mio disco rigido.

+0

Sto scaricando un file csv, puoi spiegare perché è l'evento e quando stai chiamando il clic evento all'ancora. Non ho una casella di conferma per il download del file. – Naveen

8

L'ho creato in base al post. Nota: è possibile modificare la condizione del tipo di contenuto per scaricare solo il tipo specifico di file. ad esempio (applicazione/octect-stream, application/pdf, ecc.).

package net.s4bdigital.export.main; 

import java.io.File; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.OutputStream; 
import java.util.List; 

import org.junit.Before; 
import org.junit.Test; 
import org.openqa.selenium.By; 
import org.openqa.selenium.WebDriver; 
import org.openqa.selenium.htmlunit.HtmlUnitDriver; 

import com.gargoylesoftware.htmlunit.ConfirmHandler; 
import com.gargoylesoftware.htmlunit.Page; 
import com.gargoylesoftware.htmlunit.WebClient; 
import com.gargoylesoftware.htmlunit.WebResponse; 
import com.gargoylesoftware.htmlunit.WebWindowEvent; 
import com.gargoylesoftware.htmlunit.WebWindowListener; 
import com.gargoylesoftware.htmlunit.util.NameValuePair; 

public class HtmlUnitDownloadFile { 

    protected String baseUrl; 
    protected static WebDriver driver; 

    @Before 
    public void openBrowser() { 
     baseUrl = "http://localhost/teste.html"; 
     driver = new CustomHtmlUnitDriver(); 
     ((HtmlUnitDriver) driver).setJavascriptEnabled(true); 

    } 


    @Test 
    public void downloadAFile() throws Exception { 

     driver.get(baseUrl); 
     driver.findElement(By.linkText("click to Downloadfile")).click(); 

    } 

    public class CustomHtmlUnitDriver extends HtmlUnitDriver { 

      // This is the magic. Keep a reference to the client instance 
      protected WebClient modifyWebClient(WebClient client) { 


      ConfirmHandler okHandler = new ConfirmHandler(){ 
        public boolean handleConfirm(Page page, String message) { 
         return true; 
        } 
      }; 
      client.setConfirmHandler(okHandler); 

      client.addWebWindowListener(new WebWindowListener() { 

       public void webWindowOpened(WebWindowEvent event) { 
        // TODO Auto-generated method stub 

       } 

       public void webWindowContentChanged(WebWindowEvent event) { 

        WebResponse response = event.getWebWindow().getEnclosedPage().getWebResponse(); 
        System.out.println(response.getLoadTime()); 
        System.out.println(response.getStatusCode()); 
        System.out.println(response.getContentType()); 

        List<NameValuePair> headers = response.getResponseHeaders(); 
        for(NameValuePair header: headers){ 
         System.out.println(header.getName() + " : " + header.getValue()); 
        } 

        // Change or add conditions for content-types that you would to like 
        // receive like a file. 
        if(response.getContentType().equals("text/plain")){ 
         getFileResponse(response, "target/testDownload.war"); 
        } 



       } 

       public void webWindowClosed(WebWindowEvent event) { 



       } 
      });   

      return client; 
      } 


    } 

    public static void getFileResponse(WebResponse response, String fileName){ 

     InputStream inputStream = null; 

     // write the inputStream to a FileOutputStream 
     OutputStream outputStream = null; 

     try {  

      inputStream = response.getContentAsStream(); 

      // write the inputStream to a FileOutputStream 
      outputStream = new FileOutputStream(new File(fileName)); 

      int read = 0; 
      byte[] bytes = new byte[1024]; 

      while ((read = inputStream.read(bytes)) != -1) { 
       outputStream.write(bytes, 0, read); 
      } 

      System.out.println("Done!"); 

     } catch (IOException e) { 
      e.printStackTrace(); 
     } finally { 
      if (inputStream != null) { 
       try { 
        inputStream.close(); 
       } catch (IOException e) { 
        e.printStackTrace(); 
       } 
      } 
      if (outputStream != null) { 
       try { 
        // outputStream.flush(); 
        outputStream.close(); 
       } catch (IOException e) { 
        e.printStackTrace(); 
       } 

      } 
     } 

    } 

} 
+1

Mi dispiace ma non capisco, dove o quanto esattamente stai mantenendo il riferimento a 'webclient' nel metodo' modifywebclient' ...... grazie a –

+1

https://selenium.googlecode.com/svn/trunk/ docs/api/java/org/openqa/selenio/HtmlUnit/HtmlUnitDriver.html # modifyWebClient (com.gargoylesoftware.htmlunit.WebClient) Anudeep enterprises Samaiya è un metodo di superclasse .. possiamo ignorare che l'aggiunta di una maniglia per confermare Windows del file di download .. Ma è necessario modificare il tipo di contenuto atteso nel tuo caso. –

+0

Davvero fa una magia ... Funziona bene. – viralpatel

2

C'è un modo più semplice se non si è in wrapping HtmlUnit con selenio. Fornisci semplicemente WebClient di HtmlUnit con WebWindowListener esteso.

È anche possibile utilizzare Apache commons.io per eseguire facilmente la copia in streaming.

WebClient webClient = new WebClient(); 
webClient.addWebWindowListener(new WebWindowListener() { 
    public void webWindowOpened(WebWindowEvent event) { } 

    public void webWindowContentChanged(WebWindowEvent event) { 
     // Change or add conditions for content-types that you would 
     // to like receive like a file. 
     if (response.getContentType().equals("text/plain")) { 
      try { 
       IOUtils.copy(response.getContentAsStream(), new FileOutputStream("downloaded_file")); 
      } catch (FileNotFoundException e) { 
       e.printStackTrace(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
     } 

    } 

    public void webWindowClosed(WebWindowEvent event) {} 
}); 
1
final WebClient webClient = new WebClient(BrowserVersion.CHROME); 
     webClient.getOptions().setTimeout(2000); 
     webClient.getOptions().setThrowExceptionOnScriptError(false); 
     webClient.getOptions().setThrowExceptionOnFailingStatusCode(false); 
     webClient.waitForBackgroundJavaScript(2000); 

     //get General page 
     final HtmlPage page = webClient.getPage("http://your"); 

     //get Frame 
     final HtmlPage frame = ((HtmlPage) 
     page.getFrameByName("Frame").getEnclosedPage()); 

     webClient.setConfirmHandler(new ConfirmHandler() { 
      public boolean handleConfirm(Page page, String message) { 
       return true; 
      } 
     }); 

     //get element file 
     final DomElement file = mainFrame.getElementByName("File"); 

     final InputStream xls = file.click().getWebResponse().getContentAsStream(); 

     assertNotNull(xls); 
    } 
-1

Capire l'URL di download, e raschiare in List. dall'URL di download possiamo ottenere l'intero file usando questo codice.

try{ 
     String path = "your destination path"; 
     List<HtmlElement> downloadfiles = (List<HtmlElement>) page.getByXPath("the tag you want to scrape"); 
     if (downloadfiles.isEmpty()) { 
      System.out.println("No items found !"); 
     } else { 
      for (HtmlElement htmlItem : downloadfiles) { 
       String DownloadURL = htmlItem.getHrefAttribute(); 

       Page invoicePdf = client.getPage(DownloadURL); 
       if (invoicePdf.getWebResponse().getContentType().equals("application/pdf")) { 
        System.out.println("creatign PDF:"); 
        IOUtils.copy(invoicePdf.getWebResponse().getContentAsStream(), 
          new FileOutputStream(path + "file name")); 
       } 
      } 
     } 
    } catch (Exception e) { 
     e.printStackTrace(); 
    }