前端使用预签名上传图片到腾讯云对象存储

问题遇到的现象和发生背景

腾讯云对象存储,后台获取预签名,前台通过预签名上传图片到bucket,失败

用代码块功能插入代码,请勿粘贴截图

后端获取预签名代码

package com.watching.gulimall.thirdparty.controller;

import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.auth.BasicSessionCredentials;
import com.qcloud.cos.auth.COSCredentials;
import com.qcloud.cos.http.HttpMethodName;
import com.qcloud.cos.http.HttpProtocol;
import com.qcloud.cos.region.Region;
import com.tencent.cloud.CosStsClient;
import com.tencent.cloud.Response;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author Watching
 * * @date 2022/9/28
 * * Describe:
 */
@RestController
@RefreshScope
public class CosController {

    @Value("${qcloud.SecretId}")
    String secretId;
    @Value("${qcloud.SecretKey}")
    String secretKey;
    @Value("${qcloud.bucketName}")
    String bucketName;
    @Value("${qcloud.region}")
    String region;

    @GetMapping("/test")
    public void test() {
        System.out.println("test!");
    }

    @RequestMapping("/oss/policy")
    public String policy(@RequestParam String name) {
        /**
         * 获取临时密钥
         */
        TreeMap config = new TreeMap();
        String tmpSecretId;
        String tmpSecretKey;
        String sessionToken;
        try {
            //这里的 SecretId 和 SecretKey 代表了用于申请临时密钥的永久身份(主账号、子账号等),子账号需要具有操作存储桶的权限。
            // 替换为您的云 api 密钥 SecretId
            config.put("secretId", secretId);
            // 替换为您的云 api 密钥 SecretKey
            config.put("secretKey", secretKey);

            // 设置域名:
            // 如果您使用了腾讯云 cvm,可以设置内部域名
            //config.put("host", "sts.internal.tencentcloudapi.com");

            // 临时密钥有效时长,单位是秒,默认 1800 秒,目前主账号最长 2 小时(即 7200 秒),子账号最长 36 小时(即 129600)秒
            config.put("durationSeconds", 1800);

            // 换成您的 bucket
            config.put("bucket", bucketName);
            // 换成 bucket 所在地区
            config.put("region", region);

            // 这里改成允许的路径前缀,可以根据自己网站的用户登录态判断允许上传的具体路径
            // 列举几种典型的前缀授权场景:
            // 1、允许访问所有对象:"*"
            // 2、允许访问指定的对象:"a/a1.txt", "b/b1.txt"
            // 3、允许访问指定前缀的对象:"a*", "a/*", "b/*"
            // 如果填写了“*”,将允许用户访问所有资源;除非业务需要,否则请按照最小权限原则授予用户相应的访问权限范围。
            config.put("allowPrefixes", new String[]{
                    "*"
            });

            // 密钥的权限列表。必须在这里指定本次临时密钥所需要的权限。
            // 简单上传、表单上传和分块上传需要以下的权限,其他权限列表请看 https://cloud.tencent.com/document/product/436/31923
            String[] allowActions = new String[]{
                    // 简单上传
                    "name/cos:PutObject",
                    // 表单上传、小程序上传
                    "name/cos:PostObject",
                    // 分块上传
                    "name/cos:InitiateMultipartUpload",
                    "name/cos:ListMultipartUploads",
                    "name/cos:ListParts",
                    "name/cos:UploadPart",
                    "name/cos:CompleteMultipartUpload"
            };
            config.put("allowActions", allowActions);

            Response response = CosStsClient.getCredential(config);
            tmpSecretId = response.credentials.tmpSecretId;
            tmpSecretKey = response.credentials.tmpSecretKey;
            sessionToken = response.credentials.sessionToken;
        } catch (Exception e) {
            e.printStackTrace();
            throw new IllegalArgumentException("no valid secret !");
        }

        /**
         * 使用临时密钥生成CosClient
         */
        COSCredentials cred = new BasicSessionCredentials(tmpSecretId, tmpSecretKey, sessionToken);

        // ClientConfig 中包含了后续请求 COS 的客户端设置:
        ClientConfig clientConfig = new ClientConfig();

        // 设置 bucket 的地域
        // COS_REGION 请参照 https://cloud.tencent.com/document/product/436/6224
        clientConfig.setRegion(new Region(region));

        // 设置请求协议, http 或者 https
        // 5.6.53 及更低的版本,建议设置使用 https 协议
        // 5.6.54 及更高版本,默认使用了 https
        clientConfig.setHttpProtocol(HttpProtocol.https);

        // 以下的设置,是可选的:

        // 设置 socket 读取超时,默认 30s
        clientConfig.setSocketTimeout(30*1000);
        // 设置建立连接超时,默认 30s
        clientConfig.setConnectionTimeout(30*1000);

        // 如果需要的话,设置 http 代理,ip 以及 port
        clientConfig.setHttpProxyIp("httpProxyIp");
        clientConfig.setHttpProxyPort(80);

        // 生成 cos 客户端。
        COSClient cosClient =  new COSClient(cred, clientConfig);

        /**
         * 生成预签名
         */
        // 调用 COS 接口之前必须保证本进程存在一个 COSClient 实例,如果没有则创建
// 详细代码参见本页:简单操作 -> 创建 COSClient


// 存储桶的命名格式为 BucketName-APPID,此处填写的存储桶名称必须为此格式 (已经在nacos配置中心中写好

// 对象键(Key)是对象在存储桶中的唯一标识。详情请参见 [对象键](https://cloud.tencent.com/document/product/436/13324)
        String format = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        UUID uuid = UUID.randomUUID();
        String substring = name.substring(name.lastIndexOf("."));
        String key = format+"/"+uuid+substring;

// 设置签名过期时间(可选), 若未进行设置则默认使用 ClientConfig 中的签名过期时间(1小时)
// 这里设置签名在半个小时后过期
        Date expirationDate = new Date(System.currentTimeMillis() + 30 * 60 * 1000);

// 填写本次请求的参数,需与实际请求相同,能够防止用户篡改此签名的 HTTP 请求的参数
//        Map params = new HashMap();
//        params.put("param1", "value1");

// 填写本次请求的头部,需与实际请求相同,能够防止用户篡改此签名的 HTTP 请求的头部
//        Map headers = new HashMap();
//        headers.put("header1", "value1");

// 请求的 HTTP 方法,上传请求用 PUT,下载请求用 GET,删除请求用 DELETE
        HttpMethodName method = HttpMethodName.PUT;

        URL url = cosClient.generatePresignedUrl(bucketName, key, expirationDate, method);
        System.out.println(url.toString());

// 确认本进程不再使用 cosClient 实例之后,关闭之
        cosClient.shutdown();
        return url.toString();
    }
}


前端使用预签名上传图片

axios({
                    url: this.signUrl,
                    method: "PUT",
                    data: this.file
                }).then(function (err,data){
                    console.log(err)
                    console.log(data)
                })

运行结果及报错内容

img

img

请问这是什么原因呢?