Android使用RxJava并行上傳圖片到阿里云OSS

前言

不要上錯來車了咸这,這里只是簡單的使用 RxJava來多線程上傳圖片至OSS采够。 有需要的往下看,有哪里不足的希望各位提出寶貴的意見。

OSS 配置

參考:官方文檔

1. 添加依賴

dependencies {
    compile 'com.aliyun.dpa:oss-android-sdk:+'
    compile 'com.squareup.okhttp3:okhttp:3.4.1'
    compile 'com.squareup.okio:okio:1.9.0'
}

2. 權(quán)限設(shè)置

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />

3. 混淆設(shè)置

-keep class com.alibaba.sdk.android.oss.** { *; }
-dontwarn okio.**
-dontwarn org.apache.commons.codec.binary.**

OSS 初始化

這里使用的是SDK代理更新token的方式醋安,您需要告訴SDK如何獲取Token。在SDK的應(yīng)用中斩箫,您需要實現(xiàn)一個回調(diào)里伯,這個回調(diào)通過您實現(xiàn)的方式去獲取一個Federation Token(即StsToken),然后返回崎弃。SDK會利用這個Token來進行加簽處理实蓬,并在需要更新時主動調(diào)用這個回調(diào)獲取Token

    public static void initOSS(){

        OSSCredentialProvider provider = new OSSFederationCredentialProvider() {

            @Override
            public OSSFederationToken getFederationToken() throws ClientException {
                final StsTokenBean.CredentialsBean[] credentialsBean = new StsTokenBean.CredentialsBean[1];
                final String ENDPOINT = "http://oss-cn-hangzhou.aliyuncs.com";
                RequestBody body = RequestBody.create(MediaType.parse("application/json;charset=UTF-8"), "{}");
                //從自己服務(wù)器獲取臨時的StsTkoen,使用同步的
                RetrofitFactory.Companion
                        .createInstance(true)
                        .create(CommonApi.class)
                        .getStsToken(body)
                        .subscribe(new Observer<BaseBean<StsTokenBean>>() {
                            @Override
                            public void onCompleted() {
                            }

                            @Override
                            public void onError(Throwable e) {
                            }

                            @Override
                            public void onNext(BaseBean<StsTokenBean> stsTokenBeanBaseBean) {
                                if (stsTokenBeanBaseBean != null && stsTokenBeanBaseBean.getContent()!= null && stsTokenBeanBaseBean.getContent().getCredentials() != null){
                                    credentialsBean[0] = stsTokenBeanBaseBean.getContent().getCredentials();
                                }
                            }
                        });

                if (credentialsBean[0] != null){
                    return new OSSFederationToken(credentialsBean[0].getAccessKeyId(),credentialsBean[0].getAccessKeySecret(),credentialsBean[0].getSecurityToken(),credentialsBean[0].getExpiration());
                }
                return null;
            }
        };

        ClientConfiguration conf = new ClientConfiguration();
        conf.setConnectionTimeout(15 * 1000); // 連接超時,默認15秒
        conf.setSocketTimeout(15 * 1000); // socket超時吊履,默認15秒
        conf.setMaxConcurrentRequest(5); // 最大并發(fā)請求書安皱,默認5個
        conf.setMaxErrorRetry(2); // 失敗后最大重試次數(shù),默認2次
        oss = new OSSClient(STFApplication.Companion.getContext(), ENDPOINT, provider, conf);
    }

OSS 上傳圖片

這里只是使用了簡單上傳本地文件的同步接口艇炎,有需要了解更多的請向往官方文檔

    public static Observable<PutObjectResult> upImages(final List<UpImageBean> pathList){
        if (oss == null){
            Log.e(TAG,"oss == null 沒有初始化OSS");
            return null;
        }
        if (pathList == null || pathList.size() == 0){
            Log.e(TAG,"pathList == null  圖片數(shù)組不能為空");
            return null;
        }

        int threadNum = Runtime.getRuntime().availableProcessors()+1;
        final ExecutorService executor = Executors.newFixedThreadPool(threadNum);

        //為了方便閱讀代碼這里就沒使用lambda
        return Observable.from(pathList)
                .flatMap(new Func1<UpImageBean, Observable<PutObjectResult>>() {
                    @Override
                    public Observable<PutObjectResult> call(final UpImageBean bean) {
                        return Observable.just(bean)
                                .map(new Func1<UpImageBean, PutObjectResult>() {
                                    @Override
                                    public PutObjectResult call(UpImageBean upImageBean) {
                                        PutObjectRequest put = null;
                                        try {
                                            put = new PutObjectRequest(BUCKE_NAME, upImageBean.getName(), upImageBean.getPath());
                                            return oss.putObject(put);
                                        } catch (ClientException e) {
                                            e.printStackTrace();
                                        } catch (ServiceException e) {
                                            e.printStackTrace();
                                        }
                                        return null;
                                    }
                                })
                                .subscribeOn(Schedulers.from(executor));
                    }
                })
                .subscribeOn(Schedulers.io())
                .finallyDo(() -> {
                    executor.shutdown();
                })
                .observeOn(AndroidSchedulers.mainThread());
    }

注意:這里是沒有做背壓處理的酌伊,應(yīng)為項目需求最大只上傳9張圖片。需要做背壓處理的同學(xué)就要自己做改進了缀踪。

OSSUtils.java

獻上全部代碼給各位觀眾老爺居砖,注意把 ENDPOINT ,BUCKE_NAME 改成自己的驴娃。

public class OSSUtils {

    private static final String ENDPOINT = "http://oss-cn-hangzhou.aliyuncs.com";
    private static final String BUCKE_NAME = "xxxxxx";
    private static OSS oss;
    private static final String TAG = OSSUtils.class.getSimpleName();


    public static void initOSS(){

        OSSCredentialProvider credentialProvider = new OSSFederationCredentialProvider(){

            @Override
            public OSSFederationToken getFederationToken() throws ClientException {
                return null;
            }
        };

        OSSCredentialProvider provider = new OSSFederationCredentialProvider() {

            @Override
            public OSSFederationToken getFederationToken() throws ClientException {
                final StsTokenBean.CredentialsBean[] credentialsBean = new StsTokenBean.CredentialsBean[1];
                RequestBody body = RequestBody.create(MediaType.parse("application/json;charset=UTF-8"), "{}");
                //從自己服務(wù)器獲取臨時的StsTkoen,使用同步的
                RetrofitFactory.Companion
                        .createInstance(true)
                        .create(CommonApi.class)
                        .getStsToken(body)
                        .subscribe(new Observer<BaseBean<StsTokenBean>>() {
                            @Override
                            public void onCompleted() {
                            }

                            @Override
                            public void onError(Throwable e) {
                            }

                            @Override
                            public void onNext(BaseBean<StsTokenBean> stsTokenBeanBaseBean) {
                                if (stsTokenBeanBaseBean != null && stsTokenBeanBaseBean.getContent()!= null && stsTokenBeanBaseBean.getContent().getCredentials() != null){
                                    credentialsBean[0] = stsTokenBeanBaseBean.getContent().getCredentials();
                                }
                            }
                        });

                if (credentialsBean[0] != null){
                    return new OSSFederationToken(credentialsBean[0].getAccessKeyId(),credentialsBean[0].getAccessKeySecret(),credentialsBean[0].getSecurityToken(),credentialsBean[0].getExpiration());
                }
                return null;
            }
        };

        ClientConfiguration conf = new ClientConfiguration();
        conf.setConnectionTimeout(15 * 1000); // 連接超時奏候,默認15秒
        conf.setSocketTimeout(15 * 1000); // socket超時,默認15秒
        conf.setMaxConcurrentRequest(5); // 最大并發(fā)請求書唇敞,默認5個
        conf.setMaxErrorRetry(2); // 失敗后最大重試次數(shù)蔗草,默認2次
        oss = new OSSClient(STFApplication.Companion.getContext(), ENDPOINT, provider, conf);
    }


    public static Observable<PutObjectResult> upImages(final List<UpImageBean> pathList){
        if (oss == null){
            Log.e(TAG,"oss == null 沒有初始化OSS");
            return null;
        }
        if (pathList == null || pathList.size() == 0){
            Log.e(TAG,"pathList == null  圖片數(shù)組不能為空");
            return null;
        }


        int threadNum = Runtime.getRuntime().availableProcessors();

        final ExecutorService executor = Executors.newFixedThreadPool(threadNum);

        return Observable.from(pathList)
                .flatMap(bean-> Observable.just(bean)
                    .map(upImageBean->{
                        PutObjectRequest put;
                        try {
                            put = new PutObjectRequest(BUCKE_NAME, upImageBean.getName(), upImageBean.getPath());
                            return oss.putObject(put);
                        } catch (ClientException e) {
                            e.printStackTrace();
                        } catch (ServiceException e) {
                            e.printStackTrace();
                        }
                        return null;
                    })
                    .subscribeOn(Schedulers.from(executor)))
                .subscribeOn(Schedulers.io())
                .finallyDo(()->executor.shutdown())
                .observeOn(AndroidSchedulers.mainThread());
    }

}

使用

    public void upPhotos(List<UpImageBean> pathList){
        final int[] imgCount = {0};
        OSSUtils.upImages(pathList)
                .subscribe(new Subscriber<PutObjectResult>() {
                    @Override
                    public void onCompleted() {
                        if (imgCount[0] == pathList.size()){//全部上傳成功
                            
                        }
                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onNext(PutObjectResult putObjectResult) {
                        if (putObjectResult!= null && putObjectResult.getStatusCode() == 200){//上傳成功
                            imgCount[0]++;
                        }
                    }
                });
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末咒彤,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子咒精,更是在濱河造成了極大的恐慌镶柱,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件模叙,死亡現(xiàn)場離奇詭異歇拆,居然都是意外死亡,警方通過查閱死者的電腦和手機范咨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進店門故觅,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人渠啊,你說我怎么就攤上這事输吏。” “怎么了昭抒?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵评也,是天一觀的道長。 經(jīng)常有香客問我灭返,道長盗迟,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任熙含,我火速辦了婚禮罚缕,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘怎静。我一直安慰自己邮弹,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布蚓聘。 她就那樣靜靜地躺著腌乡,像睡著了一般。 火紅的嫁衣襯著肌膚如雪夜牡。 梳的紋絲不亂的頭發(fā)上与纽,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天,我揣著相機與錄音塘装,去河邊找鬼急迂。 笑死,一個胖子當(dāng)著我的面吹牛蹦肴,可吹牛的內(nèi)容都是我干的僚碎。 我是一名探鬼主播,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼阴幌,長吁一口氣:“原來是場噩夢啊……” “哼勺阐!你這毒婦竟也來了卷中?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤皆看,失蹤者是張志新(化名)和其女友劉穎仓坞,沒想到半個月后背零,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體腰吟,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年徙瓶,在試婚紗的時候發(fā)現(xiàn)自己被綠了毛雇。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡侦镇,死狀恐怖灵疮,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情壳繁,我是刑警寧澤震捣,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站闹炉,受9級特大地震影響蒿赢,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜渣触,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一羡棵、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧嗅钻,春花似錦皂冰、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至柳弄,卻和暖如春舶胀,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背语御。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工峻贮, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人应闯。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓纤控,卻偏偏與公主長得像,于是被迫代替她去往敵國和親碉纺。 傳聞我的和親對象是個殘疾皇子船万,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,577評論 2 353

推薦閱讀更多精彩內(nèi)容

  • 點擊查看原文 Web SDK 開發(fā)手冊 SDK 概述 網(wǎng)易云信 SDK 為 Web 應(yīng)用提供一個完善的 IM 系統(tǒng)...
    layjoy閱讀 13,758評論 0 15
  • 一刻撒、iOS 直播聊天室 Demo 說明 1、源碼結(jié)構(gòu) 2耿导、AppDelegate 在 AppDelegate 中初...
    ajiao焦閱讀 2,837評論 2 7
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理声怔,服務(wù)發(fā)現(xiàn),斷路器舱呻,智...
    卡卡羅2017閱讀 134,651評論 18 139
  • OSS: Object Storage Service 初次接觸之控制臺操作 操作教程地址 開通40g/年 9塊錢...
    __damon__閱讀 7,587評論 0 7
  • 阿里云對象存儲OSS,主要是用于存儲靜態(tài)資源文件,它提供了很多方便的操作圖片的方法(縮放旋轉(zhuǎn)水印等),在實現(xiàn)了OS...
    記住你姓李閱讀 10,431評論 0 9