需求
项目是一个视频平台,像B站抖音那样,用户创作作品并上传到服务器。由于主服务器带宽较小,架构设计为客户端(Android/iOS)向阿里云OSS上传文件,之后把文件url通过接口传给后台的方式实现上传操作。
阿里云控制台操作
此处假定你已经进行了前置操作,即:创建阿里云账户->开通OSS服务->创建Bucket,没有做这些操作的话可以去度娘谷歌找找,此处不再赘述。
创建阿里云RAM账户
由于阿里云不允许客户端直接使用超管账户登录OSS,我们需要给客户端一个临时的身份用于上传文件。
STS临时授权访问OSS ←这个看看就行了,不用操作,下面有更快的
临时访问授权
快速搭建移动应用直传服务 ←根据这篇文档的指引开通STS服务
滑到下面操作步骤,只做1和2就可以了。
第2步是由后台来做的,最好的让你家后台写一个接口,你每次请求这个接口,他就使用SDK去找阿里云申请一组数据。这个config.json
是关键,前三个参数填写你步骤1创建的时候得到的值。第四个参数不管他。第五个参数指向一个文件。先new在那里,现在我们去控制台。
RAM控制台授予权限
阿里云RAM访问控制←登录这个控制台
①在左侧找到“RAM角色管理”,这里有一个在刚才步骤1的时候系统自动创建的角色,点进去,然后点击“添加权限”
②右侧会弹出一个操作面板,在这个输入框里输入“OSS”,然后点击搜到的结果,会添加到已选择里。最后点下面的确定
③然后在左侧找到“用户”,也有一个自动创建的角色,点进去,然后点击“权限管理”->“添加权限”,还是和刚才一样搜索“OSS”,全部添加
④然后我们在添加好的权限列表里面找到这一条,点蓝字进入
⑤复制策略内容的文本
复制出来内容应该长这样:
{
"Statement": [
{
"Action": "oss:*",
"Effect": "Allow",
"Resource": "*"
}
],
"Version": "1"
}
还记得刚才的config.json
吗?第五个参数指向了一个文件,这个json就是那个文件的内容。你可以存成Policy.txt
然后把config.json
改成下面这样:
{
"AccessKeyID" : "你的AccessKeyID",
"AccessKeySecret" : "你的AccessKeySecret",
"RoleArn" : "你的RoleArn",
"TokenExpireTime" : "900",
"PolicyFile": "Policy.txt"
}
OSS控制台授权
①登录 阿里云OSS控制台
②找到你创建好的bucket,点进去,然后点左侧的文件管理
,然后再点授权
③右侧会弹出操作面板,点新增授权
④授权用户选子账号
,然后下拉选单选择刚才步骤1的时候系统帮你创建的那个RAM用户,因为这里我们要上传文件,所以权限操作
选择读/写
,最后记得点确定。
Android代码操作
终于搞定了这该死的控制台,现在我们去Android Studio里面。
SDK导包
跟我读:gradle大法好!
implementation 'com.aliyun.dpa:oss-android-sdk:+'
获取临时鉴权数据
鉴权模式有STS
和RAM
两种,这里以RAM
为例
首先请求上面步骤2
的时候后台写好的接口。会得到像这样的数据:
{
"StatusCode":200,
"AccessKeyId":"STS.NTao********",
"AccessKeySecret":"**************",
"Expiration":"2020-12-28T07:58:34Z",
"SecurityToken":"这个玩意很长很长通常是以等号结尾的="
}
像上面这样的StatusCode == 200
就是请求成功了,我们要用的数据有AccessKeyId
、AccessKeySecret
、SecurityToken
这三个。
如果请求失败的话,会返回像这样的数据:
{
"StatusCode":500,
"ErrorCode":"错误码",
"ErrorMessage":"错误信息"
}
报错的时候会返回StatusCode == 500
,个人建议只要不是200都当错误处理,然后把错误码和错误信息报出来 甩锅给后台。
上传文件到OSS
kotlin代码段,此处写法参考官方文档,还在用Java的同学可以参考官方的写法,记住每个地方填什么参数就好。
阿里云官方Android SDK文档-初始化
阿里云官方Android SDK文档-简单上传
val credentialProvider = OSSStsTokenCredentialProvider(AccessKeyId, AccessKeySecret, SecurityToken)//这仨是刚才接口获取到的
//// 如果使用stsAuth鉴权模式,用下面这个构造方法,如果使用RAM鉴权模式,使用上面的构造方法
// stsServer = "STS应用服务器地址,例如http://abc.com"
// val credentialProvider = OSSAuthCredentialsProvider(stsServer);
//// 配置类如果不设置,会有默认配置。
// ClientConfiguration conf = new ClientConfiguration();
// conf.setConnectionTimeout(15 * 1000); // 连接超时,默认15秒。
// conf.setSocketTimeout(15 * 1000); // socket超时,默认15秒。
// conf.setMaxConcurrentRequest(5); // 最大并发请求数,默认5个。
// conf.setMaxErrorRetry(2); // 失败后最大重试次数,默认2次。
//endpoint是后台配置好的OSS地址,找你家后台要
val oss = OSSClient(applicationContext, endpoint, credentialProvider)
//构造上传请求
//bucketName 对应bucket的名字
//objectKey 文件保存在OSS上的路径及其文件名,比如我想存在bucket的image目录里面,文件名叫1.jpg。这里就填"image/1.jpg"
//注意:如果objectKey包含子目录,要预先在OSS控制台手动新建这个目录,或者让后台用管理员权限去新建目录,客户端的临时用户是没有权限新建目录的。
//localPath 本地的文件路径,一般的接口传啥这里就传啥
put = PutObjectRequest(bucketName, objectKey, localPath)
// 异步上传时可以设置进度回调。可以在这里操作进度条等,注意此处是IO线程,记得加runOnUiThread
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)
//走到这里就是上传完成了
//上传成功后的url不会在这里返回。可以去控制台查看一下,前面的域名是OSS配置的域名,后面直接拼接objectKey即可,是一个普通的地址,可以直接访问和下载
}
override fun onFailure(request: PutObjectRequest?, clientExcepion: ClientException?, serviceException: ServiceException?) {
//走到这里就是报错了
clientExcepion?.printStackTrace()
if (serviceException != null) {
// 服务异常。
Log.e("ErrorCode", serviceException.errorCode)
Log.e("RequestId", serviceException.requestId)
Log.e("HostId", serviceException.hostId)
Log.e("RawMessage", serviceException.rawMessage)
}
}
})
// task.cancel(); // 可以取消任务。
// task.waitUntilFinished(); // 等待任务完成。