安卓Android阿里OSS上传图片(缩略图使用)三步完成+源码例子
博主在做这块阿里OSS上传,也是踩过不少相关的坑,并且阿里的官方文档也是不是很详细,也翻阅不少文章,感觉有所不足,所以记录本文,希望对后面采坑的读者有所帮助,本文目前只针对安卓端OOS开发,并且后台是做好了相关的工作(使用已经搭建好的应用服务器),那么请往下看
本文核心要点多文件的同步上传or异步上传,单文件上传博主没踩到什么坑,读者应该比博主的聪明
1,选择图片
2,上传阿里OSS
3,发布成功
一 添加阿里OSS需要依赖(步骤一)
添加完相关依赖,我们进入步骤二,开始
//阿里云OSS上传文件的SDK,上传内层依赖okhttp网络框架
compile 'com.aliyun.dpa:oss-android-sdk:+'
compile 'com.squareup.okhttp3:okhttp:3.11.0'
compile 'com.squareup.okio:okio:1.9.0'
二 触发请求自家服务器索要授权
在触发上传的地方
1,发送自家网络请求,请求自家服务器索要授权
2, 成功返回拿到需要AccessKeyId、AccessKeySecret、SecurityToken、Expiration
3,获取这些信息后,调用阿里SDK,构建OssClient上传即可
P层的请求
/**
* 上传次数
*/
int number;
/**
* 成功上传(本地文件名作为key,阿里云地址为value)
*/
List<String> success = new ArrayList<>();
/**
* 失败上传(返回失败文件的本地地址)
*/
List<String> failure = new ArrayList<>();
public void upOss(final List<String> uris) {
//初始化
number = 1;
success.clear();
failure.clear();
mGson = new Gson();
HashMap<String, Object> map = new HashMap<>();
map.put("type", "release");
String payload = mGson.toJson(map);
//封装post请求参数
Map<String, Object> listMap = new HashMap<>();
listMap.put("code", 6022);
listMap.put("token", SPUtil.getString(mContext, Constant.LOGIN_TOKEN, ""));
listMap.put("payload", payload);
mDraftM.getVoucherAndUpload(listMap).subscribeOn(Schedulers.io()).unsubscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new FilterSubscriber<Object>() {
@Override
public void onSubscribe(Disposable d) {
}
//服务器 给OSS 上传的 秘钥
@Override
public void onNext(Object data) {
String stringData = String.valueOf(data);
try {
JSONObject jsonObject = new JSONObject(stringData);
int code = jsonObject.optInt("code");
//需要判断code的值做不同的处理
if (0 == code) {
//请求数据成功,拆分数据
Upload6022Bean bean = mGson.fromJson(stringData, Upload6022Bean.class);
if (bean != null) {
//初始化阿里云OSS 秘钥
String accessKeyId = bean.getPayload().getAccessid();
String accesskeysecret = bean.getPayload().getAccesskeysecret(); //秘钥
String securitytoken = bean.getPayload().getSecuritytoken();
String endpoint = bean.getPayload().getHost(); //https://oss-cn-shanghai.aliyuncs.com
OSSCredentialProvider credentialProvider = new OSSStsTokenCredentialProvider(accessKeyId, accesskeysecret, securitytoken);
OSS oss = new OSSClient(mContext, endpoint, credentialProvider);
mObjectKey = bean.getPayload().getDir(); //hw/test/trends/
String bucketName = bean.getPayload().getBucketName(); //kx-common
mImagUrl = bean.getPayload().getImg_url(); //https://img.kx.com
for (String path : uris) {
File file = new File(path);
mCrypt = MD5Util.crypt(path);
BitmapFactory.Options options = new BitmapFactory.Options();
BitmapFactory.decodeFile(file.getAbsolutePath(), options);
//获取图片的宽高
int height = options.outHeight;
int width = options.outWidth;
mObjectKeyPath = mObjectKey + width + "_" + height + "_" + mCrypt + ".jpg";
// 异步构造上传请求 核心代码 就下面几行 再走阿里,上传给阿里
PutObjectRequest objectRequest = new PutObjectRequest(bucketName, mObjectKeyPath, path);
oss.asyncPutObject(objectRequest, new OSSCompletedCallback<PutObjectRequest, PutObjectResult>() {
@Override
public void onSuccess(PutObjectRequest request, PutObjectResult result) {
String aliPath = mImagUrl + "/" + request.getObjectKey(); //https://img.kx.com/hw/test/trends/46546.jpg
success.add(aliPath);
if (number == uris.size()) {
//返回 上传路径,以及失败的路径
mJuhuaDialog.dissmiss();
mPublicDyVI.onOssSuccess(success, failure);
}
number++;
}
@Override
public void onFailure(PutObjectRequest request, ClientException clientException, ServiceException serviceException) {
number++;
String aliPath = mImagUrl + "/" + mObjectKey + mCrypt + ".jpg";
failure.add(aliPath);
if (number == uris.size()) {
mJuhuaDialog.dissmiss();
mPublicDyVI.onOssError(success, failure);
}
}
});
// 异步构造上传请求 end
//同步
/* PutObjectResult putObjectResult = oss.putObject(objectRequest);
String aliPath = mImagUrl + "/" + mObjectKeyPath;//https://img.vistateach.com/hw/test/trends/bf828298f10ada9eafca4c334b971a87.jpg
success.add(aliPath);
if (number == uris.size()) {
//返回 上传路径,以及失败的路径
mJuhuaDialog.dissmiss();
mPublicDyVI.onOssSuccess(success, failure);
}
number++;*/
}
} else {
//TODO 获取凭证信息失败
mPublicDyVI.onOssError(mErrorMessage);
}
} else {
mPublicDyVI.onOssError(mErrorMessage);
}
} catch (Exception e) {
e.printStackTrace();
mPublicDyVI.onOssError(mErrorMessage);
}
}
@Override
public void onComplete() {
}
@Override
public void onError(String str) {
mPublicDyVI.onOssError(str);
}
});
}
三 本文核心要点多文件的同步上传or异步上传
1,同步上传:多文件同步上传没有线程或者循环问题,就是用户体验较差,需要等待
2,异步上传: 就有上面叙述问题,上传9张,效果返回多张图一样一样,本地拼接的麻烦
问题:
这里采坑是后台没做callback体封装,不返回拼接的图片下载完整地址,博主自己移动端拼接,产生循环异步问题,我们循环地址列表,循环体里面做阿里OSS上传,就会 跑1,1的回调没回来,在2的回调,回来1和2,上传OSS2张没问题,但我们本地拼接地址出问题,导致两张图一模一样.
解决:
通过回调的onSuccess(PutObjectRequest request, PutObjectResult result ) ,拿request里面的getObjectKey来拼接,result是没有body 因为我们可爱的后台偷懒了.
异步请求核心代码
// 异步构造上传请求 核心代码 就下面几行 再走阿里,上传给阿里
PutObjectRequest objectRequest = new PutObjectRequest(bucketName, mObjectKeyPath, path);
oss.asyncPutObject(objectRequest, new OSSCompletedCallback<PutObjectRequest, PutObjectResult>() {
@Override
public void onSuccess(PutObjectRequest request, PutObjectResult result) {
String aliPath = mImagUrl + "/" + request.getObjectKey();//https://img.vistateach.com/hw/test/trends/bf828298f10ada9eafca4c334b971a87.jpg
success.add(aliPath);
if (number == uris.size()) {
//返回 上传路径,以及失败的路径
mJuhuaDialog.dissmiss();
mPublicDyVI.onOssSuccess(success, failure);
}
number++;
}
@Override
public void onFailure(PutObjectRequest request, ClientException clientException, ServiceException serviceException) {
number++;
String aliPath = mImagUrl + "/" + mObjectKey + mCrypt + ".jpg";
failure.add(aliPath);
if (number == uris.size()) {
mJuhuaDialog.dissmiss();
mPublicDyVI.onOssError(success, failure);
}
}
});
// 异步构造上传请求 end
同步上传 核心代码
//同步
/* PutObjectResult putObjectResult = oss.putObject(objectRequest);
String aliPath = mImagUrl + "/" + mObjectKeyPath;//https://img.vistateach.com/hw/test/trends/bf828298f10ada9eafca4c334b971a87.jpg
success.add(aliPath);
if (number == uris.size()) {
//返回 上传路径,以及失败的路径
mJuhuaDialog.dissmiss();
mPublicDyVI.onOssSuccess(success, failure);
}
number++;*/
}
四 额外步骤OSS缩略图应用
在原有访问地址拼接尾缀?x-oss-process=image/resize,m_fill,h_高度,w_宽度,提高图片加载速度,访问OSS定义缩略图,提高用户体验
String OSS_SMALL_PIC = "?x-oss-process=image/resize,m_fill,h_200,w_200";
运用核心代码
@Override
public void onSuccess(DyDetailBean6049.PayloadBean.NewsMapBean newsMap) {
mTvAddDate1.setText(newsMap.getAdd_date());
mTvActionText.setText(newsMap.getAction_text());
mTvDyTitle.setText("课堂标题: " + newsMap.getTitle());
mTvDyContent.setText("课堂内容: " + newsMap.getContent());
mTv_lesson_time.setText("上课时间: " + newsMap.getLesson_time());
final String img_url = newsMap.getImg_url();
if (!TextUtils.isEmpty(img_url)) {
//图片地址数组
final String[] split = img_url.split(",");
//拼接缩略图尾缀
for (int i = 0; i < split.length; i++) {
split[i] = split[i]+ AppConfig.OSS_SMALL_PIC;
}
ItemImgAdapter itemImgAdapter = new ItemImgAdapter(this, split);
mRv.setLayoutManager(new GridLayoutManager(this, 3));
mRv.setAdapter(itemImgAdapter);
itemImgAdapter.setOnItemClickListener(new LessonDetaiAdapter.OnItemClickListener() {
@Override
public void onItemClick(View view, int position) {
// 点击查看大图
Intent intent = new Intent(DyDetailActivity.this, VpActivity.class);
intent.putExtra("paths", img_url);
intent.putExtra("position", position);
startActivity(intent);
}
});
}
}