失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > Android 阿里云OSS 上传文件 使公网可以直接访问

Android 阿里云OSS 上传文件 使公网可以直接访问

时间:2024-03-17 16:07:26

相关推荐

Android 阿里云OSS 上传文件 使公网可以直接访问

1. 背景

有个Android演示项目需要上传图片/视频,并要求上传的图片/视频能在公网访问。

公司的服务器只能提供内网访问,如果公网进行访问,需要申请很繁琐的流程,且需要加上验签等各种条件,相当麻烦。

所以决定让Android App直接对接阿里云OSS,直接将文件上传到阿里云OSS上。

目标 :

实现 Android App上传图片/视频到阿里云OSS上,并使该图片/视频能直接在公网访问。

因为是Demo项目,我们为了快速实现功能,没有使用STS鉴权模式,而是直接将AccessKeyIdAccessKeySecret直接保存在终端用来加签请求,官方建议使用STS鉴权模式或自签名模式来提高安全性。

2. 接入阿里OSS

2.1 OSS信息

首先,我们需要知道OSS相关的信息

val accessKey = "你的AccessKey"val secretKey = "你的SecretKey"val endpoint = "oss-cn-"val bucketName = "my-dev-oss"

其中,endpoint 可以从访问域名和数据中心 对照表中获取

2.2 添加权限

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

2.3 添加阿里云OSS依赖

build.gradle中添加

implementation 'com.liulishuo.filedownloader:library:1.7.7'

2.4 构造OSSCredentialProvider

val accessKey = "你的AccessKey" //TODO 这里输入你的OSS的accessKeyval secretKey = "你的SecretKey" //TODO 这里输入你的OSS的secretKeyval provider: OSSCustomSignerCredentialProvider =object : OSSCustomSignerCredentialProvider() {override fun signContent(content: String): String {// 此处本应该是客户端将contentString发送到自己的业务服务器,然后由业务服务器返回签名后的content。关于在业务服务器实现签名算法// 详情请查看/document_detail/oss/api-reference/access-control/signature-header.html。客户端// 的签名算法实现请参考OSSUtils.sign(accessKey,screctKey,content)return OSSUtils.sign(accessKey,secretKey,content)}}

2.5 构造OSSClient

val endpoint = "oss-cn-"val oss: OSS = OSSClient(applicationContext, endpoint, provider)

2.6 构造上传请求

val bucketName = "my-dev-oss"val uploadFile = File(getExternalFilesDir("fodder"), "photo2.jpeg")val put = PutObjectRequest(bucketName, /*objectKey*/uploadFile.name,/*uploadFilePath*/uploadFile.path)// 异步上传时可以设置进度回调。put.progressCallback =OSSProgressCallback {request, currentSize, totalSize ->Log.d("PutObject","currentSize: $currentSize totalSize: $totalSize")}

2.7 上传文件

val task: OSSAsyncTask<*> = oss.asyncPutObject(put,object : OSSCompletedCallback<PutObjectRequest?, PutObjectResult> {override fun onSuccess(request: PutObjectRequest?, result: PutObjectResult) {Log.d("PutObject", "UploadSuccess")Log.d("ETag", result.eTag)Log.d("RequestId", result.requestId)}override fun onFailure(request: PutObjectRequest?,clientExcepion: ClientException?,serviceException: ServiceException?) {// 请求异常。clientExcepion?.printStackTrace()if (serviceException != null) {// 服务异常。Log.e("ErrorCode", serviceException.getErrorCode())Log.e("RequestId", serviceException.getRequestId())Log.e("HostId", serviceException.getHostId())Log.e("RawMessage", serviceException.getRawMessage())}}})// task.cancel(); // 可以取消任务。// task.waitUntilFinished(); // 等待上传完成。

3. 访问上传的图片/视频

3.1 对外访问的URL

上传文件成功后,要怎么访问呢,一番搜索,似乎找到了答案。

文中说,如果文件的读写权限ACL为公共读,那么文件URL的格式为https://BucketName.Endpoint/ObjectName

已知,我们OSSBucketNamemy-dev-ossEndpointoss-cn-,由于Bucket下没有文件夹,所以ObjectName直接为文件名,所以URL为http://my-dev-oss.oss-cn-/photo2.jpeg

具体详见 【OSS】上传Object后如何获取访问URL?

我们在浏览器中用这个URL进行访问

结果提示我们You have no right to access this object because of bucket acl.

似乎是缺少权限 ?

3.2 设置上传文件的权限

查阅了文档,才发现,有一个参数是用来设置上传文件的访问权限的

这就需要我们修改2.6 构造上传请求中的代码了

val bucketName = "devops-dev-oss"val put = PutObjectRequest(bucketName, /*objectKey*/uploadFile.name,/*uploadFilePath*/uploadFile.path)val metaData = ObjectMetadata()metaData.setHeader("x-oss-object-acl", "public-read")put.metadata = metaData

我们将上传文件的访问权限设置为public-read公共读,然后再进行一次上传

3.3 再次访问URL

我们修改好代码,重新上传文件后,再次在浏览器中使用3.1 对外访问的URL中的URLhttp://my-dev-oss.oss-cn-/photo2.jpeg进行访问

可以看到,文件直接就被下载下来了,这样我们就可以直接公网访问上传的文件了

4. 上传多个文件

4.1 阿里云OSS上传工具类

我们会有同时上传多个文件的需求,对此进行了封装

object AliOssUtils {val accessKey = "你的AccessKey"val secretKey = "你的SecretKey"val endpoint = "oss-cn-"val bucketName = "my-dev-oss"init {OSSLog.enableLog() //调用此方法开启日志}/*** 上传多个文件*/fun uploadFiles(application: Context,uploadFiles: List<File>,callBack: (List<String>) -> Unit) {if (uploadFiles.isEmpty()) returnvar uploadResultList = ArrayList<String>()var uploadFileCount = uploadFiles.sizevar uploadResultCount = AtomicInteger(0)uploadFiles.forEach {uploadFile(application, it) {url ->val count = uploadResultCount.addAndGet(1)if (url != null && !TextUtils.isEmpty(url)) {uploadResultList.add(url)}if (count == uploadFileCount) {callBack.invoke(uploadResultList)}}}}/*** 上传单个文件*/fun uploadFile(application: Context,uploadFile: File,callBack: ((String?) -> Unit)? = null) {val provider: OSSCustomSignerCredentialProvider =object : OSSCustomSignerCredentialProvider() {override fun signContent(content: String): String {// 此处本应该是客户端将contentString发送到自己的业务服务器,然后由业务服务器返回签名后的content。关于在业务服务器实现签名算法// 详情请查看/document_detail/oss/api-reference/access-control/signature-header.html。客户端// 的签名算法实现请参考OSSUtils.sign(accessKey,screctKey,content)return OSSUtils.sign(accessKey,secretKey,content)}}val oss: OSS = OSSClient(application, endpoint, provider)// 构造上传请求。val put = PutObjectRequest(bucketName, /*objectKey*/uploadFile.name,/*uploadFilePath*/uploadFile.path)val metaData = ObjectMetadata()//设置为公共读资源metaData.setHeader("x-oss-object-acl", "public-read")put.metadata = metaData// 异步上传时可以设置进度回调。put.progressCallback = OSSProgressCallback {request, currentSize, totalSize ->Log.d("PutObject","currentSize: $currentSize totalSize: $totalSize")}val task: OSSAsyncTask<*> = oss.asyncPutObject(put,object : OSSCompletedCallback<PutObjectRequest?, PutObjectResult> {override fun onSuccess(request: PutObjectRequest?, result: PutObjectResult) {Log.d("PutObject", "UploadSuccess")Log.d("ETag", result.eTag)Log.d("RequestId", result.requestId)val publicUrl ="http://${bucketName}.${endpoint}/${uploadFile.name}"Log.d("PutObject", "publicUrl:$publicUrl")Log.d("ZZZZ", "publicUrl:$publicUrl")callBack?.invoke(publicUrl)}override fun onFailure(request: PutObjectRequest?,clientExcepion: ClientException?,serviceException: ServiceException?) {// 请求异常。clientExcepion?.printStackTrace()if (serviceException != null) {// 服务异常。Log.e("ErrorCode", serviceException.getErrorCode())Log.e("RequestId", serviceException.getRequestId())Log.e("HostId", serviceException.getHostId())Log.e("RawMessage", serviceException.getRawMessage())}callBack?.invoke(null)}})// task.cancel(); // 可以取消任务。// task.waitUntilFinished(); // 等待上传完成。}}

4.2 使用工具类

使用起来也很简单

val selectList = ArrayList<File>()selectList.add(File(getExternalFilesDir("fodder"), "photo2.jpeg"))selectList.add(File(getExternalFilesDir("fodder"), "GOPR0045.JPG"))selectList.add(File(getExternalFilesDir("fodder"), "GX010114.MP4"))AliOssUtils.uploadFiles(this, selectList) {for (url in it) {Log.i("ZZZZ", "url:$url")}}

5.其他

参考

阿里云OSS Android 接入文档

阿里云OSS Android Demo

【OSS】上传Object后如何获取访问URL?

Android 快速集成阿里云OSS服务

Android 阿里云oss sdk接入 优化并增加多文件上传

如果觉得《Android 阿里云OSS 上传文件 使公网可以直接访问》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。