Android OkHttp + Retrofit 斷點續傳

本文連接java

前面咱們已經知道如何使用OkHttp+Retrofit下載文件。 下載文件時,可能會遇到一些意外狀況,好比網絡錯誤或是用戶暫停了下載。 再次啓動下載,若是又要從頭開始,會白白浪費前面下載好的內容。 斷點續傳功能能夠從上次中止的地方繼續下載文件。android

http範圍請求

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);
複製代碼
相關文章
相關標籤/搜索