Reanudar la descarga de archivos http en Java

URL url = new URL("http://download.thinkbroadband.com/20MB.zip"); URLConnection connection = url.openConnection(); File fileThatExists = new File(path); OutputStream output = new FileOutputStream(path, true); connection.setRequestProperty("Range", "bytes=" + fileThatExists.length() + "-"); connection.connect(); int lenghtOfFile = connection.getContentLength(); InputStream input = new BufferedInputStream(url.openStream()); byte data[] = new byte[1024]; long total = 0; while ((count = input.read(data)) != -1) { total += count; output.write(data, 0 , count); } 

en este código, bash reanudar la descarga. El archivo de destino es de 20 MB. Pero cuando detengo la descarga en 10mb, entonces contunue, obtengo un archivo con tamaño de archivo de 30MB. Parece que continúa escribiendo en el archivo, pero no se puede descargar en parte desde el servidor. Wget -c funciona muy bien con este archivo. ¿Cómo puedo reanudar la descarga de archivos?

  HttpURLConnection connection = (HttpURLConnection) url.openConnection(); if(ISSUE_DOWNLOAD_STATUS.intValue()==ECMConstant.ECM_DOWNLOADING){ File file=new File(DESTINATION_PATH); if(file.exists()){ downloaded = (int) file.length(); connection.setRequestProperty("Range", "bytes="+(file.length())+"-"); } }else{ connection.setRequestProperty("Range", "bytes=" + downloaded + "-"); } connection.setDoInput(true); connection.setDoOutput(true); progressBar.setMax(connection.getContentLength()); in = new BufferedInputStream(connection.getInputStream()); fos=(downloaded==0)? new FileOutputStream(DESTINATION_PATH): new FileOutputStream(DESTINATION_PATH,true); bout = new BufferedOutputStream(fos, 1024); byte[] data = new byte[1024]; int x = 0; while ((x = in.read(data, 0, 1024)) >= 0) { bout.write(data, 0, x); downloaded += x; progressBar.setProgress(downloaded); } 

Este no es mi código, pero funciona.

Supongo que el problema al que se enfrenta es llamar a url.openStream() después de url.openConnection() .

url.openStream() es equivalente a url.openConnection().getInputStream() . Por lo tanto, está solicitando la url dos veces. Particularmente la segunda vez, no especifica la propiedad del rango. Por lo tanto, la descarga siempre comienza al principio.

Debe reemplazar url.openStream() con connection.getInputStream() .

Mira este hilo que tiene un problema similar al tuyo . Si wget está funcionando, entonces el servidor es claramente compatible con la reanudación de las descargas. Parece que no está configurando el encabezado If-Range como se menciona en la respuesta aceptada del enlace anterior. es decir. añadir:

 // Initial download. String lastModified = connection.getHeaderField("Last-Modified"); // ... // Resume download. connection.setRequestProperty("If-Range", lastModified); 

Dado que la pregunta está etiquetada con Android: ¿Has probado usar DownloadManager ? Maneja todo esto muy bien para ti.

¿Qué tal esto?

 public static void download(DownloadObject object) throws IOException{ String downloadUrl = object.getDownloadUrl(); String downloadPath = object.getDownloadPath(); long downloadedLength = 0; File file = new File(downloadPath); URL url = new URL(downloadUrl); BufferedInputStream inputStream = null; BufferedOutputStream outputStream = null; URLConnection connection = url.openConnection(); if(file.exists()){ downloadedLength = file.length(); connection.setRequestProperty("Range", "bytes=" + downloadedLength + "-"); outputStream = new BufferedOutputStream(new FileOutputStream(file, true)); }else{ outputStream = new BufferedOutputStream(new FileOutputStream(file)); } connection.connect(); inputStream = new BufferedInputStream(connection.getInputStream()); byte[] buffer = new byte[1024*8]; int byteCount; while ((byteCount = inputStream.read(buffer)) != -1){ outputStream.write(buffer, 0, byteCount); break; } inputStream.close(); outputStream.flush(); outputStream.close(); } 

break; usada break; para probar el código …;)

Esto es lo que estoy usando para descargar el archivo en partes Actualizando la UI con el progreso.

/ ** @param callback = Para actualizar la UI con la acción apropiada

  * @param fileName = Name of the file by which downlaoded file will be saved. * @param downloadURL = File downlaoding URL * @param filePath = Path where file will be saved * @param object = Any object you want in return after download is completed to do certain operations like insert in DB or show toast */ public void startDownload(final IDownloadCallback callback, String fileName, String downloadURL, String filePath, Object object) { callback.onPreExecute(); // Callback to tell that the downloading is going to start int count = 0; File outputFile = null; // Path where file will be downloaded try { File file = new File(filePath); file.mkdirs(); long range = 0; outputFile = new File(file, fileName); /** * Check whether the file exists or not * If file doesn't exists then create the new file and range will be zero. * But if file exists then get the length of file which will be the starting range, * from where the file will be downloaded */ if (!outputFile.exists()) { outputFile.createNewFile(); range = 0; } else { range = outputFile.length(); } //Open the Connection URL url = new URL(downloadURL); URLConnection con = url.openConnection(); // Set the range parameter in header and give the range from where you want to start the downloading con.setRequestProperty("Range", "bytes=" + range + "-"); /** * The total length of file will be the total content length given by the server + range. * Example: Suppose you have a file whose size is 1MB and you had already downloaded 500KB of it. * Then you will pass in Header as "Range":"bytes=500000". * Now the con.getContentLength() will be 500KB and range will be 500KB. * So by adding the two you will get the total length of file which will be 1 MB */ final long lenghtOfFile = (int) con.getContentLength() + range; FileOutputStream fileOutputStream = new FileOutputStream(outputFile, true); InputStream inputStream = con.getInputStream(); byte[] buffer = new byte[1024]; long total = range; /** * Download the save the content into file */ while ((count = inputStream.read(buffer)) != -1) { total += count; int progress = (int) (total * 100 / lenghtOfFile); EntityDownloadProgress entityDownloadProgress = new EntityDownloadProgress(); entityDownloadProgress.setProgress(progress); entityDownloadProgress.setDownloadedSize(total); entityDownloadProgress.setFileSize(lenghtOfFile); callback.showProgress(entityDownloadProgress); fileOutputStream.write(buffer, 0, count); } //Close the outputstream fileOutputStream.close(); // Disconnect the Connection if (con instanceof HttpsURLConnection) { ((HttpsURLConnection) con).disconnect(); } else if (con instanceof HttpURLConnection) { ((HttpURLConnection) con).disconnect(); } inputStream.close(); /** * If file size is equal then return callback as success with downlaoded filepath and the object * else return failure */ if (lenghtOfFile == outputFile.length()) { callback.onSuccess(outputFile.getAbsolutePath(), object); } else { callback.onFailure(object); } } catch (Exception e) { e.printStackTrace(); callback.onFailure(object); } } 

interfaz IDownloadCallback {

  void onPreExecute(); // Callback to tell that the downloading is going to start void onFailure(Object o); // Failed to download file void onSuccess(String path, Object o); // Downloaded file successfully with downloaded path void showProgress(EntityDownloadProgress entityDownloadProgress); // Show progress } 

clase pública EntityDownloadProgress {

  int progress; // range from 1-100 long fileSize;// Total size of file to be downlaoded long downloadedSize; // Size of the downlaoded file public void setProgress(int progress) {this.progress = progress;} public void setFileSize(long fileSize) {this.fileSize = fileSize;} public void setDownloadedSize(long downloadedSize) {this.downloadedSize = downloadedSize;} } 

Tengo una forma para que tu código funcione.

  1. Primero, verifica si el archivo sale o no
  2. Si el archivo existe, configure la conexión:

     connection.setRequestProperty("Range", "bytes=" + bytedownloaded + "-"); 
  3. Si el archivo no existe, realice la misma descarga en un archivo nuevo.