一、引入
- 七牛云的官方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() {@Overridepublic 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());});}}
六、7月30日更新
为了确保图片顺序,将flatMap修改为concatMap。
注意:
emitter.onComplete();
public static void putImgs(List<String> images, QiNiuCallback qiNiuCallback) {String token = Auth.create(Constants.QINIU_AK, Constants.QINIU_SK).uploadToken(Constants.QINIU_SCOPE);// 七牛返回的文件名ArrayList<String> resultImagePath = new ArrayList<>();Observable// 依次发送list中的数据.fromIterable(images)// 变换,在这里上传图片// 修改为concatMap确保图片顺序.concatMap((Function<String, ObservableSource<String>>) path ->Observable.create((ObservableOnSubscribe<String>) emitter -> {String key = UUID.randomUUID().toString() + "." + path.split("\\.")[1];ResponseInfo responseInfo = uploadManager.syncPut(path, key, token, null);if (responseInfo.isOK()) {// 上传成功,发送这张图片的文件名emitter.onNext(key);emitter.onComplete();} else {// 上传失败,告辞emitter.onError(new IOException(responseInfo.error));}}).subscribeOn(Schedulers.io()))// 线程切换.observeOn(AndroidSchedulers.mainThread()).subscribe(response -> {resultImagePath.add(response);// 如果全部完成,调用成功接口if (resultImagePath.size() == images.size()) {qiNiuCallback.onSuccess(resultImagePath);}}, throwable -> {LogUtils.e(throwable.getMessage());qiNiuCallback.onError(throwable.getMessage());});}
七、相关链接
七牛云文档:https://developer.qiniu.com/kodo/sdk/1236/android
RxJava的简单使用:https://www.sdwfqin.com/2016/12/25/rxjava的简单使用/
