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

在这里插入图片描述

前言

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

上传

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

带进度上传

带进度上传使用uploadProgress操作符,并结合doOnNextfiltermap即可

  RxHttp.postForm("http://www.......") //发送Form表单形式的Post请求
        .add("file1", new File("xxx/1.png"))
        .add("file2", new File("xxx/2.png"))
        .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操作符,并结合doOnNextfiltermap即可

  //文件存储路径
  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的doOnNextfiltermap这3个操作符,一切都那么的相似,极大的降低了学习成本。

更多Android进阶指南 可以扫码 解锁 《Android十大板块文档》

1.Android车载应用开发系统学习指南(附项目实战)

2.Android Framework学习指南,助力成为系统级开发高手

3.2023最新Android中高级面试题汇总+解析,告别零offer

4.企业级Android音视频开发学习路线+项目实战(附源码)

5.Android Jetpack从入门到精通,构建高质量UI界面

6.Flutter技术解析与实战,跨平台首要之选

7.Kotlin从入门到实战,全方面提升架构基础

8.高级Android插件化与组件化(含实战教程和源码)

9.Android 性能优化实战+360°全方面性能调优

10.Android零基础入门到精通,高手进阶之路

敲代码不易,关注一下吧。ღ( ´・ᴗ・` ) 🤔

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值