retrofit2.0 +okhttp3 .0 +rxjava 實現本地多張圖片上傳

整理之前思考的如何通過選用的網絡框架通過rxjava鏈式編程實現本地多張圖片上傳。

本地文件相冊圖片的選取 -->多個本地文件上傳七牛-->拿到文件對應地址-->上傳七牛圖片地址到服務器

注:rxjava 的活學活用 :利用rxjava的多線程轉換和map操作集替換亢余的代碼for循環上傳。

一. 整體邏輯步驟

image.png

二. rxjava代碼具體實現

1.  interface Api.java -->定義獲取token接口
    @GET(ConfigServer.GET_TOKEN)
    Observable<UploadTokenBean> getUploadToken();

2. interface QiNiuApi.java -->定義七牛對應接口,baseUrl為七牛url
    @Multipart
    @POST("/")
    Observable<QiNiuBean> uploadImage(
    @PartMap Map<String, RequestBody> params);

3. interface Api.java -->定義客戶端上傳七牛文件地址到服務器接口
    @POST(ConfigServer.UPLOAD_FILE)
    @FormUrlEncoded
    Observable<JsonObject>
    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<UploadTokenBean> subscriber) {
    mApi.getUploadToken()
            .compose(RxUtil.<UploadTokenBean>ioMain())
            .subscribe(subscriber);
    }

  //上傳文件請求封裝
  public void uploadFile(Subscriber<JsonObject> subscriber,List<String> pictures) {
    JsonArray pictureJson = new JsonArray();
    for (String picture : pictures) {
        pictureJson.add(picture);
    }
    mApi.uploadFile(pictureJson.toString())
            .compose(RxUtil.<JsonObject>ioMain())
            .subscribe(subscriber);
    }

    注:RxUtil -->異步線程切換
    public static <T> Observable.Transformer<T, T> ioMain() {
    return new Observable.Transformer<T, T>() {
        @Override
        public Observable<T> call(Observable<T> 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<QiNiuBean> getQiNiuBean(File file, String token, String key) {
    Map<String, RequestBody> 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<String> pictures) {
        Subscriber<UploadTokenBean> tokenSubscriber = new Subscriber<UploadTokenBean>(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<String> pictures) {
    final List<String> uploadPictures = new ArrayList<>();
    Subscriber<File> fileSubscriber = new Subscriber<File>() {

        @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<String, File>() {
                @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<String> uploadPictures,
                        final List<String> pictures) {

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

        @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<String> uploadPictures) {
     final Subscriber<JsonObject> subscriber = new Subscriber<JsonObject>(mActivity) {

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

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

    Req.getInstance().uploadFile(subscriber,  uploadPictures);
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,461評論 6 532
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,538評論 3 417
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,423評論 0 375
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,991評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,761評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,207評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,268評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,419評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,959評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,782評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,983評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,528評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,222評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,653評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,901評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,678評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,978評論 2 374

推薦閱讀更多精彩內容