Возобновить загрузку файлов по HTTP в 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);
}
в этом коде я пытаюсь возобновить загрузку. Целевой файл составляет 20 МБ. Но когда я останавливаю загрузку на 10 МБ, то contunue, я получаю файл с размером файла 30 МБ. Кажется, что он продолжает писать в файл, но не может частично загрузить с сервера. Wget-c отлично работает с этим файлом. Как возобновить загрузку файлов?
7 ответов:
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); }
Это не мой код, но он работает.
Я думаю, проблема, с которой вы столкнулись, это вызов
url.openStream()
послеurl.openConnection()
.
url.openStream()
эквивалентноurl.openConnection().getInputStream()
. Следовательно, вы запрашиваете url-адрес дважды. В частности, во второй раз он не указывает свойство range. Поэтому загрузка всегда начинается с самого начала.вы должны заменить
url.openStream()
сconnection.getInputStream()
.
проверить этот поток, который имеет проблему, похожую на вашу. Если wget работает,то сервер явно поддерживает возобновление загрузки. Похоже, вы не устанавливаете
If-Range
заголовок как указано в принятой ответ на ссылку выше. то есть. добавить:// Initial download. String lastModified = connection.getHeaderField("Last-Modified"); // ... // Resume download. connection.setRequestProperty("If-Range", lastModified);
Так как вопрос помечен Android: Вы пробовали использовать DownloadManager. Он прекрасно справляется со всем этим для вас.
Как насчет этого?
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;
для проверки кода.. ;)
Это то, что я использую, чтобы загрузить файл в Нуса обновления пользовательского интерфейса с прогрессом.
/ ** @param callback = для обновления пользовательского интерфейса с соответствующим действием
* @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); } }
интерфейс 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 }
public class 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;} }