Download and write files using retrofit and rxjava

I'm downloading a modified PDF file. The way I download it is block I use the content range header to get a byte range, and then I need to write these bytes on the file. The problem is the order of writing them I'm using the flatmap () function to return an observable for each request that must be completed to download a file

.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 receives the string required by the header: range: bytes = 0-3999 Then I use the subscribe function to write the downloaded bytes

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);
                    }
                }
            });

But the problem is that the writing process is disorderly For example, if you first download range: bytes = 44959-53151, these will be the bytes first written in the file I've read about blockingobserver, but I don't know if it can solve the problem

I hope you can help me

Solution

This is a good example for downloading files and saving them to Android disk

The following is a modification of the above link example without lambda expression

Retrofit 2 interface, @ streaming is used to download large files

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

Code for downloading files and saving them to disk using retrofit 2 and rxjava Update the baseurl and URL path in the following code to the actual URL of the file you need to download

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());
                            }
                       });
}
The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>