美文网首页android功能专区Android高级技术
Android使用RxJava并行上传图片到阿里云OSS

Android使用RxJava并行上传图片到阿里云OSS

作者: 丶丶TkoRn丶丶 | 来源:发表于2018-08-18 11:47 被阅读659次

    前言

    不要上错来车了,这里只是简单的使用 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. 权限设置

    <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. 混淆设置

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

    OSS 初始化

    这里使用的是SDK代理更新token的方式,您需要告诉SDK如何获取Token。在SDK的应用中,您需要实现一个回调,这个回调通过您实现的方式去获取一个Federation Token(即StsToken),然后返回。SDK会利用这个Token来进行加签处理,并在需要更新时主动调用这个回调获取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"), "{}");
                    //从自己服务器获取临时的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); // 最大并发请求书,默认5个
            conf.setMaxErrorRetry(2); // 失败后最大重试次数,默认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  图片数组不能为空");
                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());
        }
    

    注意:这里是没有做背压处理的,应为项目需求最大只上传9张图片。需要做背压处理的同学就要自己做改进了。

    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"), "{}");
                    //从自己服务器获取临时的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); // 最大并发请求书,默认5个
            conf.setMaxErrorRetry(2); // 失败后最大重试次数,默认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  图片数组不能为空");
                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]++;
                            }
                        }
                    });
        }
    

    相关文章

      网友评论

      本文标题:Android使用RxJava并行上传图片到阿里云OSS

      本文链接:https://www.haomeiwen.com/subject/gagxiftx.html