前言
不要上錯來車了咸这,這里只是簡單的使用 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]++;
}
}
});
}