Реализация pause / resume при загрузке файла

Я пытаюсь реализовать pause / resume в моем менеджере загрузки, я ищу в Интернете и читаю несколько статей и меняю свой код по ним, но резюме кажется неправильным, любые идеи?

if (!downloadPath.exists()) downloadPath.mkdirs(); if (outputFileCache.exists()) { downloadedSize = outputFileCache.length(); connection.setAllowUserInteraction(true); connection.setRequestProperty("Range", "bytes=" + downloadedSize + "-"); connection.setConnectTimeout(14000); connection.connect(); input = new BufferedInputStream(connection.getInputStream()); output = new FileOutputStream(outputFileCache, true); input.skip(downloadedSize); //Skip downloaded size } else { connection.setConnectTimeout(14000); connection.connect(); input = new BufferedInputStream(url.openStream()); output = new FileOutputStream(outputFileCache); } fileLength = connection.getContentLength(); byte data[] = new byte[1024]; int count = 0; int __progress = 0; long total = downloadedSize; while ((count = input.read(data)) != -1 && !this.isInterrupted()) { total += count; output.write(data, 0, count); __progress = (int) (total * 100 / fileLength); } output.flush(); output.close(); input.close(); 

Solutions Collecting From Web of "Реализация pause / resume при загрузке файла"

Хорошо исправлена ​​проблема, вот мой код для других пользователей, которые хотят реализовать pause / resume:

  if (outputFileCache.exists()) { connection.setAllowUserInteraction(true); connection.setRequestProperty("Range", "bytes=" + outputFileCache.length() + "-"); } connection.setConnectTimeout(14000); connection.setReadTimeout(20000); connection.connect(); if (connection.getResponseCode() / 100 != 2) throw new Exception("Invalid response code!"); else { String connectionField = connection.getHeaderField("content-range"); if (connectionField != null) { String[] connectionRanges = connectionField.substring("bytes=".length()).split("-"); downloadedSize = Long.valueOf(connectionRanges[0]); } if (connectionField == null && outputFileCache.exists()) outputFileCache.delete(); fileLength = connection.getContentLength() + downloadedSize; input = new BufferedInputStream(connection.getInputStream()); output = new RandomAccessFile(outputFileCache, "rw"); output.seek(downloadedSize); byte data[] = new byte[1024]; int count = 0; int __progress = 0; while ((count = input.read(data, 0, 1024)) != -1 && __progress != 100) { downloadedSize += count; output.write(data, 0, count); __progress = (int) ((downloadedSize * 100) / fileLength); } output.close(); input.close(); } 

Невозможно сказать, что не так, без какой-либо дополнительной информации, однако следует отметить:

  1. Вы должны сделать запрос HTTP / 1.1 (это сложно сказать из вашего примера кода)
  2. Сервер должен поддерживать HTTP / 1.1
  3. Сервер сообщит вам, что он поддерживает с заголовком Accept-Ranges в ответе
  4. If-Range должен быть этагом, который сервер предоставил вам для ресурса, а не последним измененным временем

Вы должны проверить свой запрос диапазона на что-то простое, чтобы проверить происхождение, фактически поддерживает запрос диапазона сначала (например, curl или wget)

Я бы начал отлаживать эту строку:

 connection.setRequestProperty("Range", "bytes=" + downloadedSize + "-"); 

Так как из исходного кода невозможно определить, что такое downloadedSize , его сложно проработать дальше, но формат должен быть bytes=from-to .

Во всяком случае, я предлагаю вам использовать Apache HttpClient, чтобы избежать общих ошибок. Вот вопрос от кого-то, кто использует Apache HttpClient по аналогичной теме, и предоставляется некоторый пример кода.

Это может быть то, что ваш сервер долго реагирует (более чем на тайм-аут), или это также факт, что не все серверы поддерживают паузу-возобновление. Также стоит подумать, что погода загружается через Http, https, ftp или udp.

Pausing "может означать только чтение некоторых потоков и запись их на диск. При возобновлении вам придется использовать заголовки, чтобы указать, что осталось загрузить .

Вы можете попробовать что-то вроде:

  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); } 

И попробуйте синхронизировать вещи.

Я думаю, вам просто нужно удалить строку input.skip (downloadSize). Настройка заголовка HTTP для диапазона байтов означает, что сервер пропустит отправку этих байтов.

Скажем, у вас есть файл длиной 20 байт, состоящий из «aaaaabbbbbcccccddddd», и предположим, что перенос приостанавливается после загрузки 5 байтов. Тогда заголовок Range заставит сервер отправлять «bbbbbccccccddddd», вы должны прочитать все это содержимое и добавить его в файл – без skip (). Но вызов skip () в вашем коде пропускает «bbbbb», оставляя «cccccddddd» для загрузки. Если вы уже загрузили не менее 50% файла, то skip () исчерпает все входные данные, и ничего не произойдет.

Кроме того, все вещи в posty05's post применяются. Вы должны убедиться, что сервер поддерживает HTTP / 1.1, убедитесь, что заголовок Range поддерживается для ресурса (динамически созданный контент может его не поддерживать) и убедитесь, что ресурс не изменяется с помощью etag и даты изменения.