2013-01-19 22 views
6

Desidero scaricare una query HTTP con java, ma il download del file scaricato ha una durata indeterminata.Download di file via HTTP con lunghezza sconosciuta con Java

ho pensato che questo sarebbe abbastanza standard, così ho cercato e trovato un frammento di codice per esso: http://snipplr.com/view/33805/

ma ha un problema con la variabile contentLength. Poiché la lunghezza è sconosciuta, ottengo -1 indietro. Questo crea un errore. Quando ometto l'intero controllo su contentLength, ciò significa che devo sempre utilizzare il buffer massimo.

Ma il problema è che il file non è ancora pronto. In questo modo il colore viene riempito solo parzialmente e le parti del file vengono perse.

Se si tenta di scaricare un collegamento come http://overpass-api.de/api/interpreter?data=area%5Bname%3D%22Hoogstade%22%5D%3B%0A%28%0A++node%28area%29%3B%0A++%3C%3B%0A%29+%3B%0Aout+meta+qt%3B con lo snippet, si noterà l'errore e, quando si scarica sempre il buffer massimo per omettere l'errore, si finisce con un file XML corrotto.

C'è un modo per scaricare solo la parte pronta del file? Mi piacerebbe se questo potesse scaricare grandi file (fino a pochi GB).

risposta

19

Questo dovrebbe funzionare, ho provato e funziona per me:

void downloadFromUrl(URL url, String localFilename) throws IOException { 
    InputStream is = null; 
    FileOutputStream fos = null; 

    try { 
     URLConnection urlConn = url.openConnection();//connect 

     is = urlConn.getInputStream();    //get connection inputstream 
     fos = new FileOutputStream(localFilename); //open outputstream to local file 

     byte[] buffer = new byte[4096];    //declare 4KB buffer 
     int len; 

     //while we have availble data, continue downloading and storing to local file 
     while ((len = is.read(buffer)) > 0) { 
      fos.write(buffer, 0, len); 
     } 
    } finally { 
     try { 
      if (is != null) { 
       is.close(); 
      } 
     } finally { 
      if (fos != null) { 
       fos.close(); 
      } 
     } 
    } 
} 

Se si desidera che questo per l'esecuzione in background, semplicemente lo chiamano in un thread:

Thread download = new Thread(){ 
    public void run(){ 
     URL url= new URL("http://overpass-api.de/api/interpreter?data=area%5Bname%3D%22Hoogstade%22%5D%3B%0A%28%0A++node%28area%29%3B%0A++%3C%3B%0A%29+%3B%0Aout+meta+qt%3B"); 
     String localFilename="mylocalfile"; //needs to be replaced with local file path 
     downloadFromUrl(url, localFilename); 
    } 
}; 
download.start();//start the thread 
+2

Grazie, questo funziona . – sanderd17

+0

Ho notato che il vero problema è che il comando file.seek non funzionava correttamente in questo caso. Non ha trovato la fine del file e quindi ne stava sovrascrivendo una parte. Utilizzando un FileOutputStream risolto (dopo aver eliminato il codice di errore come avevo già fatto). – sanderd17

Problemi correlati