Android 史上最优雅的实现文件上传、下载及进度的监听-android下载文件

Android 史上最优雅的实现文件上传、下载及进度的监听-android下载文件
私信我或关注微信号:猿来如此呀,也可直接联系小编Q.Q:15o8o13652,回复:学习,获取免费学习资源包。

本文将直接使用RxHttp库实现文件上传、下载、断点下载、进度的监听,不对RxHttp做过多讲解,如果对RxHttp不了解,可以先去查阅相关资料先行了解,本文目的在于让更多的读者知道RxHttp库。

上传

 RxHttp.postForm("http://...") //发送Form表单形式的Post请求
.add("key", "value")
.add("file1", new File("xxx/1.webp")) //添加file对象
.add("file2", new File("xxx/2.webp"))
.from() //from操作符,是异步操作
.as(RxLife.asOnMain(this)) //感知生命周期,并在主线程回调
.subscribe(s -> {
//上传成功,拿到Http返回值,这里返回值为String类型
}, throwable -> {
//上传失败
});


注:如果需要对Http的返回值做解析,可在使用from操作符时,传入一个解析器Parser

带进度上传

带进度上传使用uploadProgress操作符,并结合doOnNext、filter、map即可

RxHttp.postForm("http://www.......") //发送Form表单形式的Post请求
.add("file1", new File("xxx/1.webp"))
.add("file2", new File("xxx/2.webp"))
.add("key1", "value1")//添加参数,非必须
.add("key2", "value2")//添加参数,非必须
.addHeader("versionCode", "100") //添加请求头,非必须
.uploadProgress() //注:如果需要监听上传进度,使用uploadProgress操作符
.observeOn(AndroidSchedulers.mainThread()) //主线程回调
.doOnNext(progress -> {
//上传进度回调,0-100,仅在进度有更新时才会回调,最多回调101次,最后一次回调Http执行结果
int currentProgress = progress.getProgress(); //当前进度 0-100
long currentSize = progress.getCurrentSize(); //当前已上传的字节大小
long totalSize = progress.getTotalSize(); //要上传的总字节大小
String result = progress.getResult(); //Http执行结果,最后一次回调才有内容
})
.filter(Progress::isCompleted)//过滤事件,上传完成,才继续往下走
.map(Progress::getResult) //到这,说明上传完成,拿到Http返回结果并继续往下走
.as(RxLife.as(this)) //感知生命周期
.subscribe(s -> { //s为String类型,由SimpleParser类里面的泛型决定的
//上传成功,处理相关逻辑
}, throwable -> {
//上传失败,处理相关逻辑
});


注:如果需要对Http的返回值做解析,可在使用uploadProgress操作符时,传入一个解析器Parser

下载

//文件存储路径
String destPath = getExternalCacheDir() + "/" + System.currentTimeMillis() + ".apk";
RxHttp.get("http://update.9158.com/miaolive/Miaolive.apk")
.download(destPath) //注意这里使用download操作符,并传入本地路径
.as(RxLife.asOnMain(this)) //感知生命周期,并在主线程回调
.subscribe(s -> {
//下载成功,回调文件下载路径
}, throwable -> {
//下载失败
});


带进度下载

带进度下载使用downloadProgress操作符,并结合doOnNext、filter、map即可

//文件存储路径
String destPath = getExternalCacheDir() + "/" + System.currentTimeMillis() + ".apk";
RxHttp.get("http://update.9158.com/miaolive/Miaolive.apk")
.downloadProgress(destPath) //注:如果需要监听下载进度,使用downloadProgress操作符
.observeOn(AndroidSchedulers.mainThread())
.doOnNext(progress -> {
//下载进度回调,0-100,仅在进度有更新时才会回调,最多回调101次,最后一次回调文件存储路径
int currentProgress = progress.getProgress(); //当前进度 0-100
long currentSize = progress.getCurrentSize(); //当前已下载的字节大小
long totalSize = progress.getTotalSize(); //要下载的总字节大小
String filePath = progress.getResult(); //文件存储路径,最后一次回调才有内容
})
.filter(Progress::isCompleted)//下载完成,才继续往下走
.map(Progress::getResult) //到这,说明下载完成,返回下载目标路径
.as(RxLife.as(this)) //感知生命周期
.subscribe(s -> {//s为String类型,这里为文件存储路径
//下载完成,处理相关逻辑
}, throwable -> {
//下载失败,处理相关逻辑
});


断点下载

断点下载相较于下载,仅仅是添加了RANGE头信息而已,其它没有任何差别

String destPath = getExternalCacheDir() + "/" + "Miaobo.apk";

long length = new File(destPath).length(); //已下载的文件长度

RxHttp.get("http://update.9158.com/miaolive/Miaolive.apk")

//如果文件存在,则添加 RANGE 头信息 ,从上次断开的点,开始下载

.addHeader("RANGE", "bytes=" + length + "-", length > 0)

.download(destPath)

.as(RxLife.as(this)) //加入感知生命周期的观察者

.subscribe(s -> { //s为String类型

Log.e("LJX", "breakpointDownloadAndProgress=" + s);

//下载成功,处理相关逻辑

}, throwable -> {

//下载失败,处理相关逻辑

});

带进度断点下载

带进度断点下载相较于带进度下载,仅仅是添加了RANGE头信息而已,其它没有任何差别

 String destPath = getExternalCacheDir() + "/" + "Miaobo.apk";
long length = new File(destPath).length(); //已下载的文件长度
RxHttp.get("http://update.9158.com/miaolive/Miaolive.apk")
//如果文件存在,则添加 RANGE 头信息 ,从上次断开的点,开始下载
.addHeader("RANGE", "bytes=" + length + "-", length > 0)
.downloadProgress(destPath)
.observeOn(AndroidSchedulers.mainThread()) //主线程回调
.doOnNext(progress -> {
//下载进度回调,0-100,仅在进度有更新时才会回调
int currentProgress = progress.getProgress(); //当前进度 0-100
long currentSize = progress.getCurrentSize(); //当前已下载的字节大小
long totalSize = progress.getTotalSize(); //要下载的总字节大小
})
.filter(Progress::isCompleted)//过滤事件,下载完成,才继续往下走
.map(Progress::getResult) //到这,说明下载完成,拿到Http返回结果并继续往下走
.as(RxLife.as(this)) //加入感知生命周期的观察者
.subscribe(s -> { //s为String类型
//下载成功,处理相关逻辑
}, throwable -> {
//下载失败,处理相关逻辑
});


注:上面带进度断点下载中,返回的进度会从0开始,如果需要接着上次下载的进度,则可以在downloadProgress下再添加一个map操作符,添加上次已经下载好的长度,如下:

 String destPath = getExternalCacheDir() + "/" + "Miaobo.apk";
long length = new File(destPath).length(); //已下载的文件长度
RxHttp.get("http://update.9158.com/miaolive/Miaolive.apk")
//如果文件存在,则添加 RANGE 头信息 ,从上次断开的点,开始下载
.addHeader("RANGE", "bytes=" + length + "-", length > 0)
.downloadProgress(destPath)
.map(progress -> {
if (length > 0) {//增加上次已经下载好的字节数,并更新进度
progress.addCurrentSize(length);
progress.addTotalSize(length);
progress.updateProgress();
}
return progress;
})
.observeOn(AndroidSchedulers.mainThread()) //主线程回调
.doOnNext(progress -> {
//下载进度回调,0-100,仅在进度有更新时才会回调
int currentProgress = progress.getProgress(); //当前进度 0-100
long currentSize = progress.getCurrentSize(); //当前已下载的字节大小
long totalSize = progress.getTotalSize(); //要下载的总字节大小
})
.filter(Progress::isCompleted)//过滤事件,下载完成,才继续往下走
.map(Progress::getResult) //到这,说明下载完成,拿到Http返回结果并继续往下走
.as(RxLife.as(this)) //加入感知生命周期的观察者
.subscribe(s -> { //s为String类型
//下载成功,处理相关逻辑
}, throwable -> {
//下载失败,处理相关逻辑
});


小结

好了,文件上传、下载相关就介绍到这里了,到这你会发现,涉及到进度的监听,都使用了RxJava的doOnNext、filter、map这3个操作符,一切都那么的相似,极大的降低了学习成本。怎么样?是不是很优雅,欢迎打脸!!

最后,很大一部分功劳都要归功于RxJava的强大,感谢RxJava,向它致敬!

私信我或关注微信号:猿来如此呀,回复:学习,获取免费学习资源包。

推荐阅读