当前位置: 首页 > 编程笔记 >

基于Ok+Rxjava实现断点续传下载

白镜
2023-03-14
本文向大家介绍基于Ok+Rxjava实现断点续传下载,包括了基于Ok+Rxjava实现断点续传下载的使用技巧和注意事项,需要的朋友参考一下

本文为大家分享了实现断点续传下载的具体代码,供大家参考,具体内容如下

1、基于Ok+Rxjava实现断点续传下载

2、基于Ok+Rxjava+Retrofit实现断点续传下载

最近总结一下了一下之前学过以及用到过得功能,整理了一个基于Ok+Rxjava实现断点续传下载的demo。下面先给大家展示一下使用效果吧。

 

说下我的大致思路吧:根据文件下载url按照自己定义的规则生成文件名,判断本地同路径下是否存在此文件,如果存在,文件大小与服务器上获取的文件大小一致的情况下,则生成新的文件名重新下载;如果文件比服务器获取的文件大小小,则执行断点下载,从本地文件长度处开始下载。如果文件不存在,则从0字节开始下载。

DownloadSubscribe(被观察者)中执行下载存入本地操作

核心还是:addHeader("RANGE", "bytes=" + downloadLength + "-" + contentLength)

DownLoadObserver(观察者)通过onnext(DownloadInfo downloadInfo)方法回调下载进度

下面上主要代码:

/**
 * 开始下载
 * @param url 下载请求的网址
 * @param downFileCallback 用来回调的接口
 */
 public void download(final String url, final DownFileCallback downFileCallback) {
 if (url == null || downCalls.get(url) != null) {
 return;
 }
 Observable.just(url)
 .filter(new Predicate<String>() {
  @Override
  public boolean test(String s) throws Exception {
  //过滤条件 若map中存在,则这次不下载
  return !downCalls.containsKey(s);
  }
 })
 .flatMap(new Function<String, ObservableSource<DownloadInfo>>() {
  @Override
  public ObservableSource<DownloadInfo> apply(String s) throws Exception {
  //创建下载实体类
  return Observable.just(createDownInfo(s));
  }
 })
 .map(new Function<DownloadInfo, DownloadInfo>() {
  @Override
  public DownloadInfo apply(DownloadInfo s) throws Exception {
  //根据本地是否存在此文件,来设置文件名及文件初始下载大小
  return getRealFileName(s);
  }
 })
 .flatMap(new Function<DownloadInfo, ObservableSource<DownloadInfo>>() {
  @Override
  public ObservableSource<DownloadInfo> apply(DownloadInfo downloadInfo) throws Exception {
  //创建被观察者
  return Observable.create(new DownloadSubscribe(downloadInfo));
  }
 })//下载
 .observeOn(AndroidSchedulers.mainThread())//在主线程回调
 .subscribeOn(Schedulers.io())//在子线程执行
 .subscribe(new DownLoadObserver() {//添加观察者
  @Override
  public void onNext(DownloadInfo downloadInfo) {
  super.onNext(downloadInfo);
  downFileCallback.onProgress(downloadInfo.getTotal(), downloadInfo.getProgress());
  }
 
  @Override
  public void onError(Throwable e) {
  super.onError(e);
  if (!(e instanceof SocketException)) {
  downFileCallback.onFail(e.getMessage());
  }
 
  }
 
  @Override
  public void onComplete() {
  downFileCallback.onSuccess(url);
  }
 
 });
 }
/**
 * 根据url暂停下载操作
 * @param url
 */
 public void cancel(String url) {
 Call call = downCalls.get(url);
 if (call != null) {
 call.cancel();//取消
 }
 downCalls.remove(url);
 }
 /**
 * 创建被观察者DownloadSubscribe
 */
 private class DownloadSubscribe implements ObservableOnSubscribe<DownloadInfo> {
 private DownloadInfo downloadInfo;
 
 public DownloadSubscribe(DownloadInfo downloadInfo) {
 this.downloadInfo = downloadInfo;
 }
 
 @Override
 public void subscribe(ObservableEmitter<DownloadInfo> e) throws Exception {
 String url = downloadInfo.getUrl();
 long downloadLength = downloadInfo.getProgress();//已经下载好的长度
 long contentLength = downloadInfo.getTotal();//文件的总长度
 //初始进度信息
 e.onNext(downloadInfo);
 
 Request request = new Request.Builder()
  //断点续传的核心
  .addHeader("RANGE", "bytes=" + downloadLength + "-" + contentLength)
  .url(url)
  .build();
 Call call = mClient.newCall(request);
 //根据下载url,把call存放在map中,取消的时候就可以通过call.cancle()来实现
 downCalls.put(url, call);
 Response response = call.execute();
 
 File file = new File(getTemporaryPath(), downloadInfo.getFileName());
 InputStream is = null;
 FileOutputStream fileOutputStream = null;
 try {
 is = response.body().byteStream();
 fileOutputStream = new FileOutputStream(file, true);
 byte[] buffer = new byte[2048];//缓冲数组2kB
 int len;
 while ((len = is.read(buffer)) != -1) {
  fileOutputStream.write(buffer, 0, len);
  downloadLength += len;
  downloadInfo.setProgress(downloadLength);
  e.onNext(downloadInfo);
 }
 fileOutputStream.flush();
 downCalls.remove(url);
 } finally {
 //关闭IO流
 IOUtil.closeAll(is, fileOutputStream);
 
 }
 e.onComplete();//完成
 }
 }
/**
 * 从服务器获取文件长度
 *
 * @param downloadUrl
 * @return
 */
 private long getContentLength(String downloadUrl) {
 Request request = new Request.Builder()
 .url(downloadUrl)
 .build();
 try {
 Response response = mClient.newCall(request).execute();
 if (response != null && response.isSuccessful()) {
 long contentLength = response.body().contentLength();
 response.close();
 return contentLength == 0 ? DownloadInfo.TOTAL_ERROR : contentLength;
 }
 } catch (IOException e) {
 e.printStackTrace();
 }
 return DownloadInfo.TOTAL_ERROR;
 }

从服务器获取文件长度的时候注意一下,Android P之后,也就是api 28以上禁止明文网络传输。需要在你的AndroidManifest中的application标签中声明"android:usesCleartextTraffic="true",允许应用进行明文传输。

使用方法:首先要获取sd卡权限

DownloadManager.getInstance().downloadPath(本地存在地址).download(url1, new DownFileCallback() {
  @Override
  public void onProgress(long totalSize, long downSize) {
  progress1.setMax((int) totalSize);
  progress1.setProgress((int) downSize);
  }
 
  @Override
  public void onSuccess(String url) {
  Toast.makeText(MainActivity.this, url1 + "下载完成", Toast.LENGTH_SHORT).show();
  }
 
  @Override
  public void onFail(String msg) {
  Toast.makeText(MainActivity.this, url1 + "下载失败", Toast.LENGTH_SHORT).show();
  }
 });

好了今天就到这里,希望能帮到大家,这对我来说也是一种加深印象的笔记,

下载地址demo

git地址:DownloadManager 欢迎star

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持小牛知识库。

 类似资料:
  • 本文向大家介绍基于Ok+Rxjava+retrofit实现断点续传下载,包括了基于Ok+Rxjava+retrofit实现断点续传下载的使用技巧和注意事项,需要的朋友参考一下 本文为大家分享了实现断点续传下载的具体代码,供大家参考,具体内容如下 1、基于Ok+Rxjava实现断点续传下载 2、基于Ok+Rxjava+Retrofit实现断点续传下载 上一篇博客中介绍了基于Ok+Rxjava实现断点

  • 本文向大家介绍基于断点续传下载原理的实现,包括了基于断点续传下载原理的实现的使用技巧和注意事项,需要的朋友参考一下 需求背景 动态创建的文件下载的时候希望浏览器显示下载进度 动态创建的文件希望能够分段下载 HTTP断点续传报文 要实现HTTP断点续传必须要简单了解以下几个报文。 Accept-Ranges 告诉客户端(浏览器..)服务器端支持断点续传 服务器端返回 Range 客户端告诉服务器端从

  • 本文向大家介绍PHP实现下载断点续传的方法,包括了PHP实现下载断点续传的方法的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了PHP实现下载断点续传的方法。分享给大家供大家参考。 具体实现代码如下: 希望本文所述对大家的PHP程序设计有所帮助。

  • 本文向大家介绍C# 文件下载之断点续传实现代码,包括了C# 文件下载之断点续传实现代码的使用技巧和注意事项,需要的朋友参考一下 注意,本文所说的断点续传特指 HTTP 协议中的断点续传。本文主要聊聊思路和关键代码,更多细节请参考本文附带的 demo。 工作原理 HTTP 协议中定义了一些请求/响应头,通过组合使用这些头信息。我们可以在一次 HTTP 请求中只请求一个文件中的一部分数据。这样我们就可

  • 本文向大家介绍Android通过HTTP协议实现断点续传下载实例,包括了Android通过HTTP协议实现断点续传下载实例的使用技巧和注意事项,需要的朋友参考一下 整理文档,搜刮出一个Android通过HTTP协议实现断点续传下载的代码,稍微整理精简一下做下分享。 FileDownloader.java                                                

  • 本文向大家介绍PHP大文件及断点续传下载实现代码,包括了PHP大文件及断点续传下载实现代码的使用技巧和注意事项,需要的朋友参考一下 一般来说浏览器要同时下载几个文件,比如pdf文件,会在服务器端把几个文件压缩成一个文件。但是导致的问题就是会消耗服务器的cpu和io资源。 那有没有办法,用户点了几个文件,在客户端同时下载呢? 支持html5的浏览器是可以的,html的a标签有一个属性download