如何 pause/resume 在 Android 中使用 okhttp 下载
How to pause/resume downloading with okhttp in Android
我在 android 中使用 okhttp 库下载文件。我下载成功了。但是当我暂停并恢复下载时出了点问题。
Response request = new Request.Builder().url(url).build();
ResponseBody responseBody = response.body();
File file = new File(filePath);
BufferedInputStream input = new BufferedInputStream(responseBody.byteStream());
OutputStream output;
if (isResume) {
output = new FileOutputStream(file, true);
input.skip(downloadedSize);
} else {
output = new FileOutputStream(file, false);
}
long totalByteSize = responseBody.contentLength();
byte[] data = new byte[1024];
int count = 0;
while ((count = input.read(data)) != -1) {
downloadedSize += count;
output.write(data, 0, count);
}
问题是例如文件大小为 10MB。下载 3MB 时我暂停,然后继续下载,下载完成后文件大小变为 13MB。它不是从恢复时的下载大小开始,而是从字节流的开头开始下载。所以文件变成13MB。代码有什么问题?
第一种方式
我尝试了很多代码,最后我用 BufferedSource source = responseBody.source(); 解决了; source.skip(下载大小);
Response request = new Request.Builder().url(url).build();
ResponseBody responseBody = response.body();
BufferedSource source = responseBody.source();
if(isResume)
source.skip(downloadedSize);
File file = new File(filePath);
BufferedInputStream input = new BufferedInputStream(responseBody.byteStream());
OutputStream output;
if (isResume) {
output = new FileOutputStream(file, true);
} else {
output = new FileOutputStream(file, false);
}
long currentDownloadedSize = 0;
long currentTotalByteSize = responseBody.contentLength();
byte[] data = new byte[1024];
int count = 0;
while ((count = input.read(data)) != -1) {
currentDownloadedSize += count;
output.write(data, 0, count);
}
它运行成功。我觉得我很幸运:)
第二种方式
我添加了 header 以跳过下载的字节,它起作用了。
Request.Builder requestBuilder = new Request.Builder();
if (isResume) {
requestBuilder.addHeader("Range", "bytes=" + String.valueOf(downloadedSize) + "-");
}
Response request = requestBuilder.url(url).build();
ResponseBody responseBody = response.body();
BufferedSource source = responseBody.source();
File file = new File(filePath);
BufferedInputStream input = new BufferedInputStream(responseBody.byteStream());
OutputStream output;
if (isResume) {
output = new FileOutputStream(file, true);
} else {
output = new FileOutputStream(file, false);
}
long currentDownloadedSize = 0;
long currentTotalByteSize = responseBody.contentLength();
byte[] data = new byte[1024];
int count = 0;
while ((count = input.read(data)) != -1) {
currentDownloadedSize += count;
output.write(data, 0, count);
}
val call = client.newCall(request)
call.enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
listener.onFail(e)
}
override fun onResponse(call: Call, response: Response) {
// write the stream to a file (downloading happening)
val stream = response.body?.byteStream()
}
})
// this will stop the downloading
call.cancel()
根据您的请求恢复使用 "Range" header 并将流附加到已下载的文件。
我在 android 中使用 okhttp 库下载文件。我下载成功了。但是当我暂停并恢复下载时出了点问题。
Response request = new Request.Builder().url(url).build();
ResponseBody responseBody = response.body();
File file = new File(filePath);
BufferedInputStream input = new BufferedInputStream(responseBody.byteStream());
OutputStream output;
if (isResume) {
output = new FileOutputStream(file, true);
input.skip(downloadedSize);
} else {
output = new FileOutputStream(file, false);
}
long totalByteSize = responseBody.contentLength();
byte[] data = new byte[1024];
int count = 0;
while ((count = input.read(data)) != -1) {
downloadedSize += count;
output.write(data, 0, count);
}
问题是例如文件大小为 10MB。下载 3MB 时我暂停,然后继续下载,下载完成后文件大小变为 13MB。它不是从恢复时的下载大小开始,而是从字节流的开头开始下载。所以文件变成13MB。代码有什么问题?
第一种方式
我尝试了很多代码,最后我用 BufferedSource source = responseBody.source(); 解决了; source.skip(下载大小);
Response request = new Request.Builder().url(url).build();
ResponseBody responseBody = response.body();
BufferedSource source = responseBody.source();
if(isResume)
source.skip(downloadedSize);
File file = new File(filePath);
BufferedInputStream input = new BufferedInputStream(responseBody.byteStream());
OutputStream output;
if (isResume) {
output = new FileOutputStream(file, true);
} else {
output = new FileOutputStream(file, false);
}
long currentDownloadedSize = 0;
long currentTotalByteSize = responseBody.contentLength();
byte[] data = new byte[1024];
int count = 0;
while ((count = input.read(data)) != -1) {
currentDownloadedSize += count;
output.write(data, 0, count);
}
它运行成功。我觉得我很幸运:)
第二种方式
我添加了 header 以跳过下载的字节,它起作用了。
Request.Builder requestBuilder = new Request.Builder();
if (isResume) {
requestBuilder.addHeader("Range", "bytes=" + String.valueOf(downloadedSize) + "-");
}
Response request = requestBuilder.url(url).build();
ResponseBody responseBody = response.body();
BufferedSource source = responseBody.source();
File file = new File(filePath);
BufferedInputStream input = new BufferedInputStream(responseBody.byteStream());
OutputStream output;
if (isResume) {
output = new FileOutputStream(file, true);
} else {
output = new FileOutputStream(file, false);
}
long currentDownloadedSize = 0;
long currentTotalByteSize = responseBody.contentLength();
byte[] data = new byte[1024];
int count = 0;
while ((count = input.read(data)) != -1) {
currentDownloadedSize += count;
output.write(data, 0, count);
}
val call = client.newCall(request)
call.enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
listener.onFail(e)
}
override fun onResponse(call: Call, response: Response) {
// write the stream to a file (downloading happening)
val stream = response.body?.byteStream()
}
})
// this will stop the downloading
call.cancel()
根据您的请求恢复使用 "Range" header 并将流附加到已下载的文件。