本教程主要介绍在获取到aliyun oss的三个字段accessKeyId,accessKeySecret,roleArn的信息后,在android端配置token并上传TXT文件
在官方文档中,构建一个OSSClient的实例代码如下:
String endpoint = "http://oss-cn-hangzhou.aliyuncs.com";
String stsServer = "STS应用服务器地址,例如http://abc.com"
//推荐使用OSSAuthCredentialsProvider。token过期可以及时更新
OSSCredentialProvider credentialProvider = new 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次
OSS oss = new OSSClient(getApplicationContext(), endpoint, credentialProvider);
这里使用应用服务器获取临时token来构建一个OSSClient。代码中的 OSSAuthCredentialsProvider 类也是 OSSFederationCredentialProvider的子类。
我们新建一个继承自 OSSFederationCredentialProvider 的类,重写类中的 getFederationToken() 方法,在方法中我们写入自己获取token的方法,以达到不用应用服务器就能获取到token的目的。代码如下:
import com.alibaba.sdk.android.oss.common.auth.OSSFederationCredentialProvider;
import com.alibaba.sdk.android.oss.common.auth.OSSFederationToken;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.http.ProtocolType;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import com.aliyuncs.sts.model.v20150401.AssumeRoleRequest;
import com.aliyuncs.sts.model.v20150401.AssumeRoleResponse;
public class StsService extends OSSFederationCredentialProvider {
// 目前只有"cn-hangzhou"这个region可用, 不要使用填写其他region的值
public static final String REGION_CN_HANGZHOU = "cn-hangzhou";
// 当前 STS API 版本
public static final String STS_API_VERSION = "2015-04-01";
static AssumeRoleResponse assumeRole(String accessKeyId, String accessKeySecret,
String roleArn, String roleSessionName, String policy,
ProtocolType protocolType) throws ClientException{
// 创建一个 Aliyun Acs Client, 用于发起 OpenAPI 请求
IClientProfile profile = DefaultProfile.getProfile(REGION_CN_HANGZHOU, accessKeyId, accessKeySecret);
DefaultAcsClient client = new DefaultAcsClient(profile);
// 创建一个 AssumeRoleRequest 并设置请求参数
final AssumeRoleRequest request = new AssumeRoleRequest();
request.setVersion(STS_API_VERSION);
request.setMethod(MethodType.POST);
request.setProtocol(protocolType);
long time = 3600;//15m-60m
request.setDurationSeconds(time); //这个是设置授权有效期的
request.setRoleArn(roleArn);
request.setRoleSessionName(roleSessionName);
request.setPolicy(policy);
// 发起请求,并得到response
final AssumeRoleResponse response = client.getAcsResponse(request);
return response;
}
@Override
public OSSFederationToken getFederationToken() throws com.alibaba.sdk.android.oss.ClientException {
AssumeRoleResponse response;
String[] token = new String[4];
// 只有 RAM用户(子账号)才能调用 AssumeRole 接口
// 阿里云主账号的AccessKeys不能用于发起AssumeRole请求
// 请首先在RAM控制台创建一个RAM用户,并为这个用户创建AccessKeys
String accessKeyId = "**************";
String accessKeySecret = "**************";
// RoleArn 需要在 RAM 控制台上获取
String roleArn = "**************";
// RoleSessionName 是临时Token的会话名称,自己指定用于标识你的用户,主要用于审计,或者用于区分Token颁发给谁
// 但是注意RoleSessionName的长度和规则,不要有空格,只能有'-' '.' '@' 字母和数字等字符
// 具体规则请参考API文档中的格式要求
String roleSessionName = "alice-001";
String policy = "{\n" +
" \"Version\": \"1\", \n" +
" \"Statement\": [\n" +
" {\n" +
" \"Action\": [\n" +
" \"oss:*\"\n" +
" ], \n" +
" \"Resource\": [\n" +
" \"acs:oss:*:*:*\" \n" +
" ], \n" +
" \"Effect\": \"Allow\"\n" +
" }\n" +
" ]\n" +
"}";
// 此处必须为 HTTPS
ProtocolType protocolType = ProtocolType.HTTPS;
try {
response = assumeRole(accessKeyId, accessKeySecret,roleArn, roleSessionName, policy, protocolType);
token[0] = response.getCredentials().getAccessKeyId();
token[1] = response.getCredentials().getAccessKeySecret();
token[2] = response.getCredentials().getSecurityToken();
token[3] = response.getCredentials().getExpiration();
} catch (ClientException e) {
e.printStackTrace();
}
return new OSSFederationToken(token[0],token[1],token[2],token[3]);
}
}
以上代码中有以下几点注意:
OSSCredentialProvider provider = new StsService();
OSS oss = new OSSClient(context, endpoint, provider, getConf());
上面代码帮我们获取到了临时的token,我们现在可以用这个构建的 OSSClient oss 来执行上传任务,代码如下:
PutObjectRequest put = new PutObjectRequest(bucketName,objectKey,filePath);
// 异步上传时可以设置进度回调
put.setProgressCallback(new OSSProgressCallback() {
@Override
public void onProgress(PutObjectRequest request, long currentSize, long totalSize) {
Log.d("PutObject", "currentSize: " + currentSize + " totalSize: " + totalSize);
}
});
OSSAsyncTask task = oss.asyncPutObject(put, new OSSCompletedCallback() {
@Override
public void onSuccess(PutObjectRequest request, PutObjectResult result) {
Log.d("PutObject", "UploadSuccess");
Log.d("ETag", result.getETag());
Log.d("RequestId", result.getRequestId());
}
@Override
public void onFailure(PutObjectRequest request, ClientException clientExcepion, ServiceException serviceException) {
// 请求异常
if (clientExcepion != null) {
// 本地异常如网络异常等
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());
}
}
});
需要注意的是,在第一行代码 new PutObjectRequest(bucketName,objectKey,filePath)中的三个参数:
bucketName:即为在OSS控制台创建的bucket的名称
objectKey:为在bucket中的保存路径。概括为(路径+文件名)。例如:”location/test.txt”,注意是包含文件名的。
filePath:为你要上传的文件在本地的路径。
最后贴一张效果图:
欢迎留言探讨!