Retrofit 2.0-resumable download of large files and resumable download

Source: Internet
Author: User

Retrofit 2.0-resumable download of large files and resumable download
ApiService

Write the API and execute the download interface function.

public interface ApiService {  @Streaming  @GET  Observable
 
   downloadFile(@Url String   fileUrl);}
 

Because the url is variable@ URL annotation symbol to specify, which is officially recommended for large files@ Streaming for annotation. Otherwise, IO exceptions may occur, and small files can be ignored without injection. If you want to perform resumable upload, you can add the header here, but it is not recommended to write it to the api directly. The size of each download request is different and it is better to add the interceptor.

DownLoadManager

Implements a download manager for file writing and type judgment. If you want to improve it, you can determine the http request header.Content-length,Content-type,RANGE: The first file is used to determine the file size, the second file type, and the third is where the file starts to be downloaded. If you verify the download source, you can addReferer. if the source is not the target, the download permission is not granted.

Public class DownLoadManager {private static final String TAG = "DownLoadManager"; private static String APK_CONTENTTYPE = "application/vnd. android. package-archive "; private static String PNG_CONTENTTYPE =" image/png "; private static String JPG_CONTENTTYPE =" image/jpg "; private static String fileSuffix = ""; public static boolean writeResponseBodyToDisk (Context context, ResponseBody body) {Log. d (T AG, "contentType: >>>" + body. contentType (). toString (); String type = body. contentType (). toString (); if (type. equals (APK_CONTENTTYPE) {fileSuffix = ". apk ";} else if (type. equals (PNG_CONTENTTYPE) {fileSuffix = ". png ";} // others are added to the String path = context. getExternalFilesDir (null) + File. separator + System. currentTimeMillis () + fileSuffix; Log. d (TAG, "path: >>>" + path); try {// todo change t He file location/name according to your needs File futureStudioIconFile = new File (path); InputStream inputStream = null; OutputStream outputStream = null; try {byte [] fileReader = new byte [4096]; long fileSize = body. contentLength (); long fileSizeDownloaded = 0; inputStream = body. byteStream (); outputStream = new FileOutputStream (futureStudioIconFile); while (true) {int read = inputStream. read (FileReader); if (read =-1) {break;} outputStream. write (fileReader, 0, read); fileSizeDownloaded + = read; Log. d (TAG, "file download:" + fileSizeDownloaded + "of" + fileSize);} outputStream. flush (); return true;} catch (IOException e) {return false;} finally {if (inputStream! = Null) {inputStream. close ();} if (outputStream! = Null) {outputStream. close () ;}} catch (IOException e) {return false ;}

}
The above is just a simple judgment on different types of files. For other types, referThe http protocol description type is added by the user. resumable data transfer is not implemented yet. There are many download introductions Based on HttpClinet. The key idea is to recordRANGE to the database. Each row to be downloaded corresponds to one piece of data. The download ID is a unique primary key, includingFilename,FileSize, fileType, downTime, downRangeThe status can basically meet the multi-thread data download requirements. After the program fit is combined with RXJava, the thread security problem is solved. To achieve multi-thread download, the so yi z will be used. I will not do much here.

Call download
 OkHttpClient okHttpClient = new OkHttpClient.Builder() .build(); Retrofit retrofit = new Retrofit.Builder() .client(okHttpClient) .baseUrl(url) .build();Api Service apiService = retrofit.create(ApiService.class);apiService..download(url1, new Subscriber  () { @Override public void onCompleted() { } @Override public void onError(Throwable e) { } @Override public void onNext(ResponseBody responseBody) { if (DownLoadManager.writeResponseBodyToDisk(MainActivity.this, responseBody)) { Toast.makeText(MainActivity.this, "Download is sucess", Toast.LENGTH_LONG).show(); } } }); } }); 

WhenHowever, we can add the progress of the last download to the header to achieve the basic breakpoint download. Currently, the multi-thread download is mainly implemented by the following ideas in the industry, when we request the total length of the file, we can divide the Three-segment size interval to enable three new threads to download the file. After the download is complete, we can use a unique file ID, you can append the three files to a single file. Of course, you do not need to enable a new thread when using retrofit in combination with RxJava. You just need to Subscriber the Subscriber to the IO thread, note that you need to determine the final file size and HashCode to verify the file integrity. Otherwise, there is no big difference between video file packet loss and the maximum frame is stuck, however, the apk packet is lost but cannot be parsed and installed.

The breakpoint download posture is enabled!

Breakpoint download apiServiece
@GET@StreamingObservable  > download(@Header("Range") String range, @Url String url); 
API

** DownLoadInfo ** s contains name, lenth,. url, and so on. It will not be pasted here. View the API directly

DownloadTypeThe records must include stats, mLastModify, downloded, savepath, etc.

 public Observable  download(@NonNull final String url, @NonNull final String saveName, @Nullable final String savePath) {return downloadDispatcher(url, saveName, savePath);}private Observable  downloadDispatcher(final String url, final String saveName, final String savePath) { return getDownloadType(url) .flatMap(new Func1  >() { @Override public Observable  call(DownloadType type) { try { type.prepare(); } catch (IOException | ParseException e) { return Observable.error(e); } try { return type.start(); } catch (IOException e) { return Observable.error(e); } } }) .doOnCompleted(new Action0() { @Override public void call() { mDownloadManager.delete(url); } }) .doOnError(new Action1  () { @Override public void call(Throwable throwable) { mDownloadManager.delete(url); } }) .doOnUnsubscribe(new Action0() { @Override public void call() { mDownloadManager.delete(url) });}     

Start download:

 @Override Observable  start() { Log.i(TAG, "Normal download start!!"); return mDownloadHelper.getDownloadApi().download(null, mUrl) .subscribeOn(Schedulers.io()) .flatMap(new Func1  , Observable  >() { @Override public Observable  call(final Response  response) { return normalSave(response); } }).onBackpressureLatest().retry(new Func2  () { @Override public Boolean call(Integer integer, Throwable throwable) { return mDownloadHelper.retry(integer, throwable); } }); }      
Call
 DownloadAgenti.getInstance(mContext) .observeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Subscriber  () { @Override public void onCompleted() { // todo } @Override public void onError(Throwable e) { todo } @Override public void onNext(final DownloadStatus status) { todo } }); 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.