springboot整合阿里云OSS做服务端签名让微信小程序文件直传OSS

1 篇文章 0 订阅
1 篇文章 0 订阅

springboot整合阿里云OSS做服务端签名让微信小程序文件直传OSS

1、需求:

想让小程序直接上传图片、文件到OSS存储,不需要经过我的服务器接收文件再转发到OSS存储。

好处
  • 可以减轻自己服务器的压力,和不必要的麻烦。

  • 有利于维护和扩展(比如扩容、迁移等等)。

  • 可以更加快的存储到OSS中,不需要多次来回传输。

  • 不占用自己服务器的带宽,阿里的OSS节点处理更快。

  • 等等。。。

2、基本原理介绍(官方描述,我觉得很简单了)

在这里插入图片描述

服务端签名后前端(小程序)直传的原理如下:

  1. 用户发送请求到自己服务器获取上传的Policy和签名。
  2. 自己的服务器返回前端直传oss需要Policy和签名给用户。
  3. 用户直接上传数据到OSS。

3、springboot 搞起来

1.新建一个springboot 项目,添加依赖

<!--阿里oss-->
<dependency>
    <groupId>com.aliyun.oss</groupId>
    <artifactId>aliyun-sdk-oss</artifactId>
    <version>2.8.3</version>
</dependency>

2.编写一个OSS的配置类(可以根据自己的需求来,注入等方式都可以)

public class AliOssConfig {
    /**
     * 填写您的AccessKeyId
     */
    public final static String accessId = "xxxx";
    /**
     * 填写您的AccessKeySecret
     */
    public final static String accessKey = "xxxxx";
    /**
     * 填写您的 endpoint(地域节点),就是你OSS的区域节点的域名
     */
    public final static String endpoint = "xxxx.aliyuncs.com";
    /**
     * 填写您的 bucketName ,就是你再OSS创建Bucket的名称
     */
    public final static String bucket = "xxx";
    /**
     * 直传地址,格式为 bucketName.endpoint (Bucket域名)
     */
    public final static String host = "https://" + bucket +"."+ endpoint;

    /*
     * ============= 配置上传过期时间、大小等等 =========
     */
    /**
     * 上传截止时间(秒)
     */
    public final static long expireTime = 30;

    /**
     * 上传文件最小(字节)
     */
    public final static long min = 0;
    /**
     * 上传文件最大(字节)
     */
    public final static long max = 1048576000;

    /**
     * 上传文件的前缀、可忽略
     */
    public final static String dir = "user/";
}

3.创建controller

@RestController
@RequestMapping("/ali/oss")
public class AliOssController {
    /**
     * 创建OSS客户端
     */
    private OSSClient client = new OSSClient(AliOssConfig.endpoint, AliOssConfig.accessId, AliOssConfig.accessKey);

    /**
     * 前端获取直传的policy信息
     * 前端可以使用响应的参数进行直传到oss存储
     *
     * @return
     */
    @GetMapping("/policy")
    public AliOssPolicy getPolicy() {
        // 直传有效截止时间
        long expireEndTime = System.currentTimeMillis() + (AliOssConfig.expireTime * 1000);
        Date expiration = new Date(expireEndTime);
        PolicyConditions policyConditions = new PolicyConditions();
        // 设置可上传文件的大小
        policyConditions.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, AliOssConfig.min, AliOssConfig.max);
        // 设置上传文件的前缀、可忽略
        policyConditions.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, AliOssConfig.dir);
        // 生成policy
        String postPolicy = client.generatePostPolicy(expiration, policyConditions);
        byte[] binaryData = postPolicy.getBytes(StandardCharsets.UTF_8);
        String encodedPolicy = BinaryUtil.toBase64String(binaryData);
        String postSignature = client.calculatePostSignature(postPolicy);
        // 封装policy等信息
        AliOssPolicy aliOssPolicy = new AliOssPolicy();
        aliOssPolicy.setOssAccessKeyId(AliOssConfig.accessId);
        aliOssPolicy.setPolicy(encodedPolicy);
        aliOssPolicy.setSignature(postSignature);
        aliOssPolicy.setDir(AliOssConfig.dir);
        aliOssPolicy.setHost(AliOssConfig.host);
        aliOssPolicy.setExpire(String.valueOf(expireEndTime / 1000));
        return aliOssPolicy;
    }
}

4.创建一个封装类来响应给前端

public class AliOssPolicy implements Serializable {
    /**
     * 上传认证id
     */
    private String ossAccessKeyId;
    /**
     * policy
     */
    private String policy;
    /**
     * 签名
     */
    private String signature;
    /**
     * 直传文件的开头(路径)
     */
    private String dir;
    /**
     * 直传地址
     */
    private String host;
    /**
     * 上传截止时间
     */
    private String expire;
	
    // get和set省略
}

完成!

4、postman请求测试

http://localhost:8080/ali/oss/policy
{
    // 认证key
    "ossAccessKeyId": "xxxx",
    // 签名后的数据
    "policy": "xxxx",
    // 文件前缀
    "dir": "xxx/",
    // 前端直传的地址
    "host": "https://xxx.xxxx.aliyuncs.com",
    // 有效截止时间
    "expire": "1583592220"
}

5、小程序 搞起来

// 调用小程序api选择图片上传
    wx.chooseImage({
      success: function(res) {
        var tempFilePaths = res.tempFilePaths
        // 上传图片到oss
        wx.uploadFile({
          // 直传的oss地址
          url: 'https://xxxx.xxxx.aliyuncs.com',
          // 上传的文件
          filePath: tempFilePaths[0],
          // 必须为file
          name: 'file',
          // 表单数据
          formData: {
            // key:文件路径,如 user/666.png
            //直接 key: "${filename}" 是存放在根目录,文件名为上传的文件名
            // 如果后端签名时指定了dir则开头必须同后端的一致,如后端指定了 “user/” 开头则必须是 user/xxx.xx
            key: "user/666.png",
            // 自定义成功响应值 ,默认响应204
            success_action_status: '200',
            OssAccessKeyId: 'xxxx',
            // 后端签名后发回的policy
            policy: 'xxxxxx',
            // 后端返回的签名
            signature: 'xxxxx'
          },
          success: function(res) {
            if (res.statusCode == 200) {
              console.log("上传成功!")
              console.log(res)
            } else {
              console.log("上传失败!")
              console.log(res)
            }
          },
          fail(error) {
            console.log("上传错误")
            console.log(error)
          }
        })
      }
    })

6、上传测试:

在这里插入图片描述

OSS管理客户端

在这里插入图片描述

直传OSS中可能出现的错误

Post Object常见错误如下表所示。

序号错误原因解法
1ErrorCode: MalformedPOSTRequest ErrorMessage: The body of your POST request is not well-formed multipart/form-data表单域格式不符合要求表单域格式请查看表后的 Post Object表单域格式
2ErrorCode: InvalidAccessKeyId ErrorMessage: The OSS Access Key Id you provided does not exist in our records.AccessKeyID禁用或不存在,或者过期的临时用户AccessKeyID,或者临时用户没有提供STS Token排查方法请查看InvalidAccessKeyId错误排查
3ErrorCode: AccessDenied ErrorMessage: Invalid according to Policy: Policy expired.表单域Policy中的expiration过期请调整Policy中的expiration,注意expiration的格式ISO8601 GMT
4ErrorCode: AccessDenied ErrorMessage: SignatureDoesNotMatch The request signature we calculated does not match the signature you provided. Check your key and signing method.签名错误签名方法请查看下面的Post Object的签名
5ErrorCode: InvalidPolicyDocument ErrorMessage: Invalid Policy: Invalid Simple-Condition: Simple-Conditions must have exactly one property specified.请求中Policy至少包含一个condition请查看表后的Post Object的Policy格式
6ErrorCode: InvalidPolicyDocument ErrorMessage: Invalid Policy: Invalid JSON: unknown char e请求中的Policy格式不正确请检查Policy格式,"是否加缺失,转义字符是否加\
7ErrorCode: InvalidPolicyDocument ErrorMessage: Invalid Policy: Invalid JSON: , or ] expected请求中的Policy格式不正确请检查Policy中是否缺少,]
8ErrorCode: AccessDenied ErrorMessage: Invalid according to Policy: Policy Condition failed: [“starts-with”, “$key”, “user/eric/“]请求指定的KeyPolicy限定的不符请检查请求中表单域Key的值
9ErrorCode: AccessDenied ErrorMessage: Invalid according to Policy: Policy Condition failed: [“eq”, “$bucket”, “mingdi-bjx”]请求指定BucketPolicy限定的不符请检查endpoint中的Bucket的值
10ErrorCode: AccessDenied ErrorMessage: Invalid according to Policy: Policy Condition failed: [“starts-with”, “$x-oss-meta-prop”, “prop-“]请求指定的文件元数据x-oss-meta-prop与policy限定的不符请检查请求中的x-oss-meta-prop的值
11ErrorCode: AccessDenied ErrorMessage: Invalid according to Policy: Policy Condition failed: [“eq”, “ f i e l d ” , “ {field}”, “ field,{value}”]表单域中指定的{field}Policy中限定的值不符,或者在请求中没有指定请检查请求中的{field}的值
12ErrorCode: AccessDenied ErrorMessage: You have no right to access this object because of bucket acl.当前用户无权限请查看OSS权限问题及排查
13ErrorCode: InvalidArgument ErrorMessage: The bucket POST must contain the specified ‘key’. If it is specified, please check the order of the fields表单域没有指定Key,或者放在了表单域file请添加表单域Key或调整顺序

喜欢的话点个赞再走呀!

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值