阿里云OSS上传文件

Aliyun OSS 上传文件

本教程主要介绍在获取到aliyun oss的三个字段accessKeyId,accessKeySecret,roleArn的信息后,在android端配置token并上传TXT文件

重写 OSSFederationCredentialProvider 类

在官方文档中,构建一个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]);
    }
}

以上代码中有以下几点注意:

  1. String policy 字段等同于官方Android demo中的三个权限配置文件,这里是可读可写权限。
  2. 重写的 getFederationToken() 方法会返回一个 OSSFederationToken 类。使用以下语句来构建一个客户端:
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:为你要上传的文件在本地的路径。

最后贴一张效果图:

阿里云OSS上传文件_第1张图片

欢迎留言探讨!

你可能感兴趣的:(Android)