本文連接java
前面咱們已經知道如何使用OkHttp+Retrofit下載文件。 下載文件時,可能會遇到一些意外狀況,好比網絡錯誤或是用戶暫停了下載。 再次啓動下載,若是又要從頭開始,會白白浪費前面下載好的內容。 斷點續傳功能能夠從上次中止的地方繼續下載文件。android
Range 是一個請求首部,告知服務器返回文件的哪一部分。 在一個 Range 首部中,能夠一次性請求多個部分,服務器會以 multipart 文件的形式將其返回。 若是服務器返回的是範圍響應,須要使用 206 Partial Content 狀態碼。 假如所請求的範圍不合法,那麼服務器會返回 416 Range Not Satisfiable 狀態碼,表示客戶端錯誤。 服務器容許忽略Range首部,從而返回整個文件,狀態碼用200。git
示例github
Range: <unit>=<range-start>-
Range: <unit>=<range-start>-<range-end>
Range: <unit>=<range-start>-<range-end>, <range-start>-<range-end>
Range: <unit>=<range-start>-<range-end>, <range-start>-<range-end>, <range-start>-<range-end>
複製代碼
發起請求時,通常Range的內容寫成 bytes=0-100 這樣的形式。 或者請求多個部分時,指定多個範圍。bash
Range: bytes=200-1000, 2000-6576, 19000-
複製代碼
Content-Range 表示主體長度或者尺寸。服務器
參考:網絡
developer.mozilla.org/zh-CN/docs/…app
參考 github.com/RustFisher/…ide
使用OkHttp添加Range頭部,告知服務器咱們須要的文件數據範圍。url
定義的方法中要求傳入 @Header("Range")
private interface ApiService {
@Streaming
@GET
Observable<ResponseBody> downloadPartial(@Url String url, @Header("Range") String range);
}
複製代碼
須要傳入的Range字符串形如 bytes=200-1000
retrofit.create(ApiService.class)
.downloadPartial(callBack.getUrl(), "bytes=" + startByte + "-")
.subscribeOn(Schedulers.newThread())
.observeOn(Schedulers.io())
.doOnNext(new Consumer<ResponseBody>() {
@Override
public void accept(ResponseBody responseBody) throws Exception {
callBack.saveFile(responseBody);
}
})
.doOnError(new Consumer<Throwable>() {
@Override
public void accept(Throwable throwable) throws Exception {
tellDownloadError(callBack.getUrl(), throwable);
}
})
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<ResponseBody>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(ResponseBody responseBody) {
}
@Override
public void onError(Throwable e) {
callBack.setState(DownloadTaskState.ERROR);
tellDownloadError(callBack.getUrl(), e);
}
@Override
public void onComplete() {
}
});
複製代碼
咱們也能夠在下載前,先去檢查文件已下載的部分的大小,再決定Range範圍。 續傳時,寫入本地文件注意選擇流的append模式。
fos = new FileOutputStream(file, true);
複製代碼