一, 引入
七牛云的官方 SDK 中只有单图上传. 如果想要实现多图的上传可能会想到 for 循环, 递归等解决方案. 在这里我分享下我用 RxJava + 回调接口封装的七牛云多图上传工具类, 也算是之前看了老多 RxJava 文章的一个实践吧. 如有不妥之处, 还请多多指教啦
二, 先简单说下七牛
我们公司的项目是图片直接由客户端上传的七牛, 然后在给我们服务器传七牛的地址.
引入依赖
implementation 'com.qiniu:qiniu-android-sdk:7.3.+'
复制代码
七牛的图片上传
- // 吐槽一下: token 官方推荐服务器生成, 可是我司都是客户端自己搞...
- // UploadManager uploadManager = new UploadManager(config);
data = <File 对象, 或 文件路径, 或 字节数组>
String key = <指定七牛服务上的文件名, 或 null>;
String token = <从服务端 SDK 获取>;
- uploadManager.put(data, key, token,
- new UpCompletionHandler() {
- @Override
- public void complete(String key, ResponseInfo info, JSONObject res) {
- //res 包含 hash,key 等信息, 具体字段取决于上传策略的设置
- if(info.isOK()) {
- Log.i("qiniu", "Upload Success");
- } else {
- Log.i("qiniu", "Upload Fail");
- // 如果失败, 这里可以把 info 信息上报自己的服务器, 便于后面分析上传错误原因
- }
- Log.i("qiniu", key + ",\r\n" + info + ",\r\n" + res);
- }
- }, null);
复制代码
三, 在说几个 Rxjava 的方法哈哈
fromIterable(发送原始数据, 图片地址集合)
可以接收一个 Iterable 容器作为输入, 每次发射一个元素
flatMap(将图片地址转为七牛云上传成功后的文件名, 具体看代码吧)
FlatMap 操作符使用一个指定的函数对原始 Observable 发射的每一项数据执行变换操作, 这个函数返回一个本身也发射数据的 Observable, 然后 FlatMap 合并这些 Observables 发射的数据, 最后将合并后的结果当做它自己的数据序列发射.
compose(切换线程)
compose()是唯一一个能够从数据流中得到原始 Observable 的操作符, 所以, 那些需要对整个数据流产生作用的操作 (比如, subscribeOn() 和 observeOn())需要使用 compose()来实现.
为什么不用 compose 进行变换
答: 因为 compose 是操作的整个流, FlatMap 是操作的单独的事件.
四, 工具类代码
- public class QiNiuUtils {
- private static String token = "一般是找自己服务器要";
- /**
- * 七牛云 SDK
- */
- private static UploadManager uploadManager = new UploadManager();
- /**
- * 回调接口
- */
- public interface QiNiuCallback {
- /**
- * 上传完成
- */
- void onSuccess(List<String> picUrls);
- /**
- * 上传失败
- */
- void onError(String msg);
- }
- /**
- * 上传图片到七牛
- *
- * @param images 图片地址
- * @param qiNiuCallback 回调接口
- */
- @SuppressLint("CheckResult")
- public static void putImgs(List<String> images, QiNiuCallback qiNiuCallback) {
- // 七牛返回的文件名
- ArrayList<String> resultImagePath = new ArrayList<>();
- Observable
- // 依次发送 list 中的数据
- .fromIterable(images)
- // 变换, 在这里上传图片
- .flatMap((Function<String, ObservableSource<String>>)
- path -> Observable.create(emitter -> {
- String key = UUID.randomUUID().toString() + "." + path.split("\\.")[1];
- uploadManager.put(path, key, token,
- (key1, info, res) -> {
- //res 包含 hash,key 等信息, 具体字段取决于上传策略的设置
- if (info.isOK()) {
- // 上传成功, 发送这张图片的文件名
- emitter.onNext(key1);
- } else {
- // 上传失败, 告辞
- emitter.onError(new IOException(info.error));
- }
- }, null);
- })
- )
- // 线程切换
- .compose(RxUtil.rxObservableSchedulerHelper())
- .subscribe(response -> {
- resultImagePath.add(response);
- // 如果全部完成, 调用成功接口
- if (resultImagePath.size() == images.size()) {
- qiNiuCallback.onSuccess(resultImagePath);
- }
- }, throwable -> {
- LogUtils.e(throwable.getMessage());
- qiNiuCallback.onError(throwable.getMessage());
- });
- }
- }
复制代码
五, 如何调用
- // pathResult 是图片地址集合
- if (pathResult.size()> 0) {
- showProgress();
- QiNiuUtils.putImgs(pathResult, new QiNiuUtils.QiNiuCallback() {
- @Override
- public void onSuccess(List<String> picUrls) {
- LogUtils.i(picUrls.toString());
- showMsg("图片上传完成!");
- hideProgress();
- }
- @Override
- public void onError(String msg) {
- hideProgress();
- }
- });
- }
来源: https://juejin.im/post/5b5bd75cf265da0f6132160a