腾讯云对象存储,后台获取预签名,前台通过预签名上传图片到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)
})
请问这是什么原因呢?