retrofit2.0 +okhttp3 .0 +rxjava 实现本地多张图片上传

整理之前思考的如何通过选用的网络框架通过rxjava链式编程实现本地多张图片上传。

本地文件相册图片的选取 -->多个本地文件上传七牛-->拿到文件对应地址-->上传七牛图片地址到服务器

注:rxjava 的活学活用 :利用rxjava的多线程转换和map操作集替换亢余的代码for循环上传。

一. 整体逻辑步骤

retrofit2.0 +okhttp3 .0 +rxjava 实现本地多张图片上传_第1张图片
image.png

二. rxjava代码具体实现

1.  interface Api.java -->定义获取token接口
    @GET(ConfigServer.GET_TOKEN)
    Observable getUploadToken();

2. interface QiNiuApi.java -->定义七牛对应接口,baseUrl为七牛url
    @Multipart
    @POST("/")
    Observable uploadImage(
    @PartMap Map params);

3. interface Api.java -->定义客户端上传七牛文件地址到服务器接口
    @POST(ConfigServer.UPLOAD_FILE)
    @FormUrlEncoded
    Observable
    uploadFile(@Field(ConfigServer.PICTURES) String pictures);

4. class Req.java --> 代理模式封装类,retrofit 获取Api实现类,封装请求
    private Req() {
        Retrofit retrofit = BaseApi.getRetrofit();
        mApi = retrofit.create(Api.class);
    }

   //获取token请求封装
    public void getUploadToken(Subscriber subscriber) {
    mApi.getUploadToken()
            .compose(RxUtil.ioMain())
            .subscribe(subscriber);
    }

  //上传文件请求封装
  public void uploadFile(Subscriber subscriber,List pictures) {
    JsonArray pictureJson = new JsonArray();
    for (String picture : pictures) {
        pictureJson.add(picture);
    }
    mApi.uploadFile(pictureJson.toString())
            .compose(RxUtil.ioMain())
            .subscribe(subscriber);
    }

    注:RxUtil -->异步线程切换
    public static  Observable.Transformer ioMain() {
    return new Observable.Transformer() {
        @Override
        public Observable call(Observable tObservable) {
            return tObservable.subscribeOn(Schedulers.io())
                    .unsubscribeOn(AndroidSchedulers.mainThread())
                    .observeOn(AndroidSchedulers.mainThread());
            }
        };
      }

5. QiNiuReq.java --> 代理模式封装类,retrofit 获取QiNiuApi实现类,封装请求
    private QiNiuReq() {
        Retrofit retrofit = BaseThirdApi.getRetrofit(BASE_URL);
        mQiNiuApi = retrofit.create(QiNiuApi.class);
    }

    //获取七牛上传图片地址封装请求
    public Observable getQiNiuBean(File file, String token, String key) {
    Map params = new HashMap<>();
    params.put("file", RequestBody.create(MediaType.parse("image/jpeg"), file));
    params.put("token", RequestBody.create(MediaType.parse("text/plain"), token));
    params.put("key", RequestBody.create(MediaType.parse("text/plain"), key));
    return mQiNiuApi.uploadImage(params);
    }

6. FileUtils.java --> 循环质压缩图片至200kb以下
   /**
     * 压缩图片
     *
     * @param context         当前上下文
     * @param reqWidth        需要压缩的宽度尺寸
     * @param reqHeight       需要压缩的高度尺寸
     * @param maxCompressSize 压缩的最大图片大小,kb为单位
     * @param filePath        需要被压缩的图片文件路径
     * @return 成功压缩后的图片文件路径
     */
    public static File compressPicBySampleSize(Context context, int reqWidth, int reqHeight, int maxCompressSize, String filePath) {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(filePath, options);
        int outWidth = options.outWidth;
        int outHeight = options.outHeight;
        options.inSampleSize = findBestSampleSize(outWidth, outHeight, reqWidth, reqHeight);
        options.inJustDecodeBounds = false;

        Bitmap bitmap = BitmapFactory.decodeFile(filePath, options);
        File file = new File(StorageUtils.getCacheDirectory(context, "image"), System.currentTimeMillis() + ".jpg");
        BufferedOutputStream bos = null;
        int quality = 100;
        do {
            if (quality < 20) {
                break;
            }
            try {
                bos = new BufferedOutputStream(new FileOutputStream(file));
                bitmap.compress(Bitmap.CompressFormat.JPEG, quality, bos);
                bos.flush();
                quality -= 10;
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                IoUtils.closeStream(bos);
            }
        } while (file.length() > 1024 * maxCompressSize);
        if (null != bitmap && !bitmap.isRecycled()) {
            bitmap.recycle();
        }
        return file;
      }

7. UploadPre.java --> 整体步骤通过rxjava串起来的逻辑交互类
    
    --> rxjava链式编程:获取服务器token值
    public void uploadProcess(final List pictures) {
        Subscriber tokenSubscriber = new Subscriber(mActivity) {
            @Override
            public void onNextAction(final UploadTokenBean bean) {
            compressFile(bean, title, content, orderId, products, pictures, themes, tags);
            }

            @Override
            public void onErrorAction(int code) {
        };                          
    Req.getInstance().getUploadToken(tokenSubscriber);
    }

    --> rxjava 通过map集合:将本地图片压缩后返回压缩文件路径
    private void compressFile(final UploadTokenBean bean,final List pictures) {
    final List uploadPictures = new ArrayList<>();
    Subscriber fileSubscriber = new Subscriber() {

        @Override
        public void onCompleted() {

        }

        @Override
        public void onError(Throwable e) {
            mView.uploadFileFailed(-1);
        }

        @Override
        public void onNext(File file) {
            getQiNiuBean(file, bean,uploadPictures,pictures);
        }
    };

    Observable.from(pictures).
            subscribeOn(Schedulers.io())
            .map(new Func1() {
                @Override
                public File call(String picture) {
                    return ImageUtil.compressPicBySampleSize(mActivity, 1000, 1000, 200, picture);
                }
            })
            .observeOn(Schedulers.io())
            .subscribe(fileSubscriber);
    }

--> rxjava 链式编程 :上传本地图片到QiNiu服务器
private void getQiNiuBean(final File file,
                        final UploadTokenBean bean,
                        final List uploadPictures,
                        final List pictures) {

    String key = Md5Utils.getFileMD5(file) + "." + FileUtil.getMineType(file);
    SubscriberAdapter uploadSubscriber = new SubscriberAdapter() {

        @Override
        public void onCompleted() {
            if (pictures.size() == uploadPictures.size()) {
                upLoadFile( uploadPictures);
            }
        }

        @Override
        public void onError(Throwable e) {
            if (mRetryCount > 0) {
                mRetryCount--;
                getQiNiuBean(file, bean, uploadPictures, pictures);
            } else {
                mRetryCount = 3;
                mView.uploadFileFailed(-1);
            }
        }

        @Override
        public void onNext(QiNiuBean qiNiuBean) {
            uploadPictures.add(qiNiuBean.getKey());
        }
    };

    QiNiuReq.getInstance().getQiNiuBean(file, bean.getToken(),     key).subscribe(uploadSubscriber);
}

--> rxjava 链式编程:上传文件七牛地址到服务器
     private void upLoadFile(List uploadPictures) {
     final Subscriber subscriber = new Subscriber(mActivity) {

        @Override
        public void onNextAction(JsonObject jsonObject) {                        
             mView.upLoadFileSucceed();
        }

        @Override
        public void onErrorAction(int code) {
            mView.uploadFileFailed(code);
        }
    };

    Req.getInstance().uploadFile(subscriber,  uploadPictures);
}

你可能感兴趣的:(retrofit2.0 +okhttp3 .0 +rxjava 实现本地多张图片上传)