使用Retrofit和RxJava下载并编写文件

前端之家收集整理的这篇文章主要介绍了使用Retrofit和RxJava下载并编写文件前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在下载一个改装的pdf文件,我下载它的方式是块.我使用Content-Range标头获取一个字节范围,然后我需要在文件上写这些字节,问题是编写它们的顺序.我正在使用flatMap()函数为每个下载文件必须完成的请求返回一个observable.
.flatMap(new Func1<Integer,Observable<Response>>() {
                @Override
                public Observable<Response> call(Integer offset) {
                    int end;

                    if (offset + BLOCK_SIZE > (contentLength - 1))
                        end = (int) contentLength - 1 - offset;

                    else
                        end = offset + BLOCK_SIZE;

                    String range = getResources().getString(R.string.range_format,offset,end);

                   return ApiAdapter.getApiService().downloadPDFBlock(range);
                }
            })

downloadPDFBlock接收标头所需的字符串:Range:bytes = 0-3999.然后我使用subscribe函数写下载的字节

subscribe(new Subscriber<Response>() {
                @Override
                public void onCompleted() {
                    Log.i(LOG_TAG,file.getAbsolutePath());
                }

                @Override
                public void onError(Throwable e) {
                    e.printStackTrace();
                }

                @Override
                public void onNext(Response response) {
                    writeInCache(response);
                    }
                }
            });

但问题是写作过程是无序的.例如:如果首先下载Range:bytes = 44959-53151,这些将是首先在文件中写入的字节.我已经阅读了有关BlockingObserver但我不知道这是否可以解决问题.

我希望你能帮助我.

解决方法

这是一个很好的 example用于下载文件并将其保存到Android中的磁盘.

以下是不使用lambda表达式的上述链接示例的修改.

Retrofit 2界面,@ Streaming用于下载大文件.

public interface RetrofitApi {
    @Streaming
    @GET
    Observable<Response<ResponseBody>> downloadFile(@Url String fileUrl);
}

使用Retrofit 2和rxjava下载文件并将其保存到磁盘的代码.将下面代码中的baseUrl和url路径更新为您需要下载的文件的实际URL.

public void downloadZipFile() {
    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl("https://my.resources.com/")
            .client(new OkHttpClient.Builder().build())
            .addCallAdapterFactory(RxJavaCallAdapterFactory.create()).build();
    RetrofitApi downloadService = retrofit.create(RetrofitApi.class);

    downloadService.downloadFile("resources/archive/important_files.zip")
            .flatMap(new Func1<Response<ResponseBody>,Observable<File>>() {
                @Override
                public Observable<File> call(final Response<ResponseBody> responseBodyResponse) {
                    return Observable.create(new Observable.OnSubscribe<File>() {
                        @Override
                        public void call(Subscriber<? super File> subscriber) {
                            try {
                                // you can access headers of response
                                String header = responseBodyResponse.headers().get("Content-Disposition");
                                // this is specific case,it's up to you how you want to save your file
                                // if you are not downloading file from direct link,you might be lucky to obtain file name from header
                                String fileName = header.replace("attachment; filename=","");
                                // will create file in global Music directory,can be any other directory,just don't forget to handle permissions
                                File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsoluteFile(),fileName);

                                BufferedSink sink = Okio.buffer(Okio.sink(file));
                                // you can access body of response
                                sink.writeAll(responseBodyResponse.body().source());
                                sink.close();
                                subscriber.onNext(file);
                                subscriber.onCompleted();
                            } catch (IOException e) {
                                e.printStackTrace();
                                subscriber.onError(e);
                            }
                        }
                    });
                }
            })
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Observer<File>() {
                            @Override
                            public void onCompleted() {
                                Log.d("downloadZipFile","onCompleted");
                            }

                            @Override
                            public void onError(Throwable e) {
                                e.printStackTrace();
                                Log.d("downloadZipFile","Error " + e.getMessage());
                            }

                            @Override
                            public void onNext(File file) {
                                Log.d("downloadZipFile","File downloaded to " + file.getAbsolutePath());
                            }
                       });
}

猜你在找的Java相关文章