Android开发中,服务端签名后上传文件到阿里云OSS

官方文档:https://help.aliyun.com/document_detail/31920.html
可能我太菜了,官方文档写的很多东西感觉不全,或者不好找,按照下面这些步骤,可能更好理解并实践成功。

一.开通子用户

oss管理控制台
根据文档

二.设置各种权限

文档:使用STS临时访问凭证访问OSS
开通子用户以后,这个文档了解STS临时访问原理
进入RAM控制台

1.创建RAM用户

在这里插入图片描述
访问密钥一定要保存好,只有创建的时候能看到

2.为RAM用户添加STS服务权限

  1. 单击已创建RAM用户右侧对应的添加权限
  2. 添加权限页面,选择AliyunSTSAssumeRoleAccess权限。在这里插入图片描述

3. 创建用于获取临时访问凭证的角色(用于给RAM用户授权)

在这里插入图片描述
角色名自己起,最好有特定含义。保存 ARN

4.为角色授权上传文件的权限

创建上传文件的自定义权限策略

  1. 在左侧导航栏的权限管理菜单下,单击权限策略管理。
  2. 单击创建权限策略
  3. 在新建自定义权限策略页面,填写策略名称为RamTestPolicy[最好与角色名称保存相关,这样意义更明确],配置模式选择脚本配置,并在策略内容中赋予角色向目标存储空间examplebucket这个是你自己要上传的bucket】下的目录exampledir这是是你允许这个角色上传数据能保存的文件夹】上传文件的权限。
{
   "Version": "1",
   "Statement": [
    {
          "Effect": "Allow",
          "Action": [
            "oss:PutObject"
          ],
          "Resource": [
            "acs:oss:*:*:examplebucket/exampledir",
            "acs:oss:*:*:examplebucket/exampledir/*"
          ]
    }
   ]
}
  1. 点击确定

创建完自定义权限,给角色授予这个自定义的权限

  1. 在左侧导航栏的身份管理菜单下,单击角色
  2. 角色页面,找到目标RAM角色RamOssTest【你刚创建的角色名】。
  3. 单击RAM角色RamOssTest右侧的添加权限
  4. 添加权限页面下的自定义策略页签,选择已创建的自定义权限策略RamTestPolicy。
  5. 单击确定

注意: 上面这个自定义的策略,只允许了角色 上传文件、其只能上传到examplebucket这个bucket中的exampledir这个文件夹中,后续如果上地址不是这个文件夹就会报权限错误:You have no right to access this object because of bucket acl
也可以配置其他更多的、更精细的权限,文档:RAM Policy常见示例

三、获取临时访问凭证,服务器端接口开发

文档中有他们自己编的比较原生的各种语言的服务端接口,
因为同时做web开发,所有自己写了一个接口,开发框架用了spring boot【其实和SSM一样,只不过配置更简单】
接口代码根据官方文档改的。
服务端接口代码:

@RestController //就是普通的Controller 再加 将响应体以json格式返回  即@ResponseBody
public class OssController {

    @Autowired
    OSS ossClient;
	//配置文件中取出accessId、sts_endpoint、accessKeySecret、roleArn这些值
    @Value("${spring.cloud.alicloud.access-key}")
    private String accessId;
    @Value("${sts_endpoint}")
    private String sts_endpoint;
    @Value("${roleArn}")
    private String roleArn;
    @Value("${roleSessionName}")
    private String roleSessionName;
    @Value("${spring.cloud.alicloud.secret-key:}")
    private String accessKeySecret;

    /**
     * 获取临时访问凭证
     * @return
     */
    @RequestMapping("/oss/sts")
    public R sts(){
        // 自定义角色会话名称,用来区分不同的令牌,例如可填写为SessionTest。
        String roleSessionName = "SessionTest";

        String policy = "{\n" +
                "    \"Version\": \"1\", \n" +
                "    \"Statement\": [\n" +
                "        {\n" +
                "            \"Action\": [\n" +
                "                \"oss:PutObject\"\n" +
                "            ], \n" +
                "            \"Resource\": [\n" +
                "                \"acs:oss:*:*:sleep-monitor/*\" \n" +
                "            ], \n" +
                "            \"Effect\": \"Allow\"\n" +
                "        }\n" +
                "    ]\n" +
                "}";
        Map<String, Object> respMap = null;
        try {
            // regionId表示RAM的地域ID。以华东1(杭州)地域为例,regionID填写为cn-hangzhou。也可以保留默认值,默认值为空字符串("")。
            String regionId = "cn-beijing";
            // 添加endpoint。
            DefaultProfile.addEndpoint(regionId, "Sts", sts_endpoint);
            // 构造default profile。
            IClientProfile profile = DefaultProfile.getProfile(regionId, accessId, accessKeySecret);
            // 构造client。
            DefaultAcsClient client = new DefaultAcsClient(profile);
            final AssumeRoleRequest request = new AssumeRoleRequest();
            request.setSysMethod(MethodType.POST);
            request.setRoleArn(roleArn);
            request.setRoleSessionName(roleSessionName);
            request.setPolicy(policy); // 如果policy为空,则用户将获得该角色下所有权限。
            request.setDurationSeconds(3600L); // 设置临时访问凭证的有效时间为3600秒。
            final AssumeRoleResponse response = client.getAcsResponse(request);
            respMap = new HashMap<>();
            System.out.println("Expiration: " + response.getCredentials().getExpiration());
            System.out.println("Access Key Id: " + response.getCredentials().getAccessKeyId());
            System.out.println("Access Key Secret: " + response.getCredentials().getAccessKeySecret());
            System.out.println("Security Token: " + response.getCredentials().getSecurityToken());
            System.out.println("RequestId: " + response.getRequestId());

            respMap.put("Expiration",response.getCredentials().getExpiration());
            respMap.put("AccessKeyId",response.getCredentials().getAccessKeyId());
            respMap.put("AccessKeySecret",response.getCredentials().getAccessKeySecret());
            respMap.put("SecurityToken",response.getCredentials().getSecurityToken());
            respMap.put("RequestId",response.getCredentials().getAccessKeyId());
            respMap.put("StatusCode",200);

            return R.ok(respMap);

        } catch (ClientException e) {
            System.out.println("Failed:");
            System.out.println("Error code: " + e.getErrCode());
            System.out.println("Error message: " + e.getErrMsg());
            System.out.println("RequestId: " + e.getRequestId());
            return R.error().put("data",e);
        }
    }
}

不管以那种方式写服务端,要求是能正确返回如下的json数据,
包括StatusCode、AccessKeyId、AccessKeySecret、SecurityToken、Expiration

{
    "StatusCode":200,
    "AccessKeyId":"STS.3p***dgagdasdg",
    "AccessKeySecret":"rpnwO9***tGdrddgsR2YrTtI",
	"SecurityToken":"CAES+wMIARKAAZhjH0EUOIhJMQBMjRywXq7MQ/cjLYg80Aho1ek0Jm63XMhr9Oc5s˙∂˙∂3qaPer8p1YaX1NTDiCFZWFkvlHf1pQhuxfKBc+mRR9KAbHUefqH+rdjZqjTF7p2m1wJXP8S6k+G2MpHrUe6TYBkJ43GhhTVFMuM3BZajY3VjZWOXBIODRIR1FKZjIiEjMzMzE0MjY0NzM5MTE4NjkxMSoLY2xpZGSSDgSDGAGESGTETqOio6c2RrLWRlbW8vKgoUYWNzOm9zczoqOio6c2RrLWRlbW9KEDExNDg5MzAxMDcyNDY4MThSBTI2ODQyWg9Bc3N1bWVkUm9sZVVzZXJgAGoSMzMzMTQyNjQ3MzkxMTg2OTExcglzZGstZGVtbzI=",
   	"Expiration":"2017-12-12T07:49:09Z"
}

运行服务端,并测试,访问你的服务地址,看是否能正确的返回json数据
在这里插入图片描述

四、安卓手机上传文件到阿里云OSS

首先需要引入oss依赖:文档

  • 可以直接在Android Studio环境中添加:
implementation 'com.aliyun.dpa:oss-android-sdk:2.9.10'
  • 也可以引入jar包
    将aliyun-oss-sdk-android-2.9.5.jar、okhttp-3.x.x.jar、okio-1.x.x.jar 3个jar包导入libs目录。
    jar包百度网盘下载:
    链接:https://pan.baidu.com/s/1Odc6kDM2_6rlbjo3s_aepA
    提取码:lyg6

【我在build.gradle文件中直接添加依赖的时候,出现了依赖个okhttp jar包冲突, 所以选择了第二种方式】

然后直接上代码:

    private void uploadFileTest() {

        if (HttpUtil.isNetworkAvailable(requireActivity())) {//判断是否有网络
            String endpoint = "oss-cn-beijing.aliyuncs.com";
            String buckName = "sleep-monitor";
            String stsServer = RequestCallback.baseAddress + "api/thirdparty/oss/sts";//请求sts的地址
            // 推荐使用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(MyApplication.getAppContext(), endpoint, credentialProvider);
            File[] files = MyApplication.getAppContext().getExternalFilesDirs(null);//获取该应用文件下的内部存储位置
            File file = new File(files[0],"20211013脑电丢包测试20211013191115.csv");//要上传的文件
            //第二个变量是上传的文件夹,这个文件夹必须是之前自定义权限中写的那个文件夹
            PutObjectRequest put = new PutObjectRequest(buckName, "睡眠APP/APP测试.txt", String.valueOf(file));
            try {
                Log.d(TAG,"开始上传...");
                PutObjectResult putResult = oss.putObject(put);
                Log.d(TAG,"PutObject: UploadSuccess");
                Log.d(TAG,"ETag:" + putResult.getETag());
                Log.d(TAG,"RequestId:" + putResult.getRequestId());
            } catch (ClientException e) {
                // 客户端异常,例如网络异常等。
                Log.e(TAG,"客户端异常:" + e);
                e.printStackTrace();
            } catch (ServiceException e) {
                // 服务端异常。
                Log.e(TAG,"RequestId:" + e.getRequestId());
                Log.e(TAG,"ErrorCode:"+ e.getErrorCode());
                Log.e(TAG,"HostId:"+ e.getHostId());
                Log.e(TAG,"RawMessage:"+ e.getRawMessage());
            }
        } else {
            ToastUtil.showShortToast(MyApplication.getAppContext().getResources().getString(R.string.network_enable));
        }
    }

还有异步上传可以看阿里云文档-简单上传

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

甲 烷

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值