基于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
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: node.js基础知识汇总