feat: cos upload support
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
package org.dromara.inspection.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 腾讯云COS配置属性
|
||||
*
|
||||
* @author LionLi
|
||||
*/
|
||||
@Data
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "tencent.cos")
|
||||
public class TencentCosProperties {
|
||||
|
||||
/**
|
||||
* 腾讯云SecretId
|
||||
*/
|
||||
private String secretId;
|
||||
|
||||
/**
|
||||
* 腾讯云SecretKey
|
||||
*/
|
||||
private String secretKey;
|
||||
|
||||
/**
|
||||
* 临时密钥有效期(秒),默认1800秒=30分钟
|
||||
*/
|
||||
private Integer durationSeconds = 1800;
|
||||
|
||||
/**
|
||||
* 存储桶名称
|
||||
*/
|
||||
private String bucket;
|
||||
|
||||
/**
|
||||
* 存储桶所在地域
|
||||
*/
|
||||
private String region;
|
||||
|
||||
/**
|
||||
* 腾讯云AppId
|
||||
*/
|
||||
private String appId;
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
package org.dromara.inspection.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import com.tencent.cloud.CosStsClient;
|
||||
import com.tencent.cloud.Policy;
|
||||
import com.tencent.cloud.Response;
|
||||
import com.tencent.cloud.Statement;
|
||||
import com.tencent.cloud.cos.util.Jackson;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.common.core.domain.R;
|
||||
import org.dromara.common.log.annotation.Log;
|
||||
import org.dromara.common.log.enums.BusinessType;
|
||||
import org.dromara.common.redis.utils.RedisUtils;
|
||||
import org.dromara.inspection.config.TencentCosProperties;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
/**
|
||||
* 腾讯云COS临时凭证Controller
|
||||
*
|
||||
* @author LionLi
|
||||
*/
|
||||
@Slf4j
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/inspection/cos")
|
||||
public class TencentCosController {
|
||||
|
||||
private final TencentCosProperties cosProperties;
|
||||
|
||||
private static final String CACHE_KEY = "inspection:cos:credential";
|
||||
private static final int CACHE_EXPIRE_SECONDS = 1500; // 缓存25分钟,临时密钥30分钟过期
|
||||
|
||||
/**
|
||||
* 获取腾讯云COS临时上传凭证
|
||||
*/
|
||||
@SaCheckPermission("inspection:step:edit")
|
||||
@Log(title = "获取COS临时凭证", businessType = BusinessType.OTHER)
|
||||
@GetMapping("/credential")
|
||||
public R<Response> getCredential() {
|
||||
// 先从缓存获取
|
||||
Response cachedCredential = RedisUtils.getCacheObject(CACHE_KEY);
|
||||
if (cachedCredential != null) {
|
||||
return R.ok(cachedCredential);
|
||||
}
|
||||
|
||||
try {
|
||||
// 构建配置参数
|
||||
TreeMap<String, Object> config = new TreeMap<>();
|
||||
config.put("secretId", cosProperties.getSecretId());
|
||||
config.put("secretKey", cosProperties.getSecretKey());
|
||||
config.put("durationSeconds", cosProperties.getDurationSeconds());
|
||||
config.put("bucket", cosProperties.getBucket());
|
||||
config.put("region", cosProperties.getRegion());
|
||||
|
||||
// 初始化 policy
|
||||
Policy policy = new Policy();
|
||||
|
||||
// 开始构建一条 statement
|
||||
Statement statement = new Statement();
|
||||
// 声明设置的结果是允许操作
|
||||
statement.setEffect("allow");
|
||||
|
||||
// 添加操作权限
|
||||
statement.addActions(new String[]{
|
||||
// 简单上传
|
||||
"cos:PutObject",
|
||||
"cos:PostObject",
|
||||
// 分块上传
|
||||
"cos:InitiateMultipartUpload",
|
||||
"cos:ListMultipartUploads",
|
||||
"cos:ListParts",
|
||||
"cos:UploadPart",
|
||||
"cos:CompleteMultipartUpload"
|
||||
});
|
||||
|
||||
// 设置允许操作的资源路径(限定只能上传到audio目录)
|
||||
// 格式: qcs::cos:{region}:uid/{appid}:{bucket}/{path}
|
||||
statement.addResources(new String[]{
|
||||
"qcs::cos:" + cosProperties.getRegion() +
|
||||
":uid/" + cosProperties.getAppId() +
|
||||
":" + cosProperties.getBucket() +
|
||||
"/audio/*"
|
||||
});
|
||||
|
||||
// 把一条 statement 添加到 policy
|
||||
policy.addStatement(statement);
|
||||
|
||||
// 将 Policy 实例转化成 String
|
||||
config.put("policy", Jackson.toJsonPrettyString(policy));
|
||||
|
||||
// 获取临时密钥
|
||||
Response response = CosStsClient.getCredential(config);
|
||||
|
||||
// 缓存凭证(25分钟,临时密钥30分钟过期)
|
||||
RedisUtils.setCacheObject(CACHE_KEY, response, Duration.ofSeconds(CACHE_EXPIRE_SECONDS));
|
||||
|
||||
return R.ok(response);
|
||||
} catch (Exception e) {
|
||||
log.error("获取临时COS凭证失败", e);
|
||||
return R.fail("获取临时凭证失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取COS配置信息(供前端使用)
|
||||
*/
|
||||
@SaCheckPermission("inspection:step:edit")
|
||||
@GetMapping("/config")
|
||||
public R<Map<String, String>> getConfig() {
|
||||
Map<String, String> config = new HashMap<>();
|
||||
config.put("bucket", cosProperties.getBucket());
|
||||
config.put("region", cosProperties.getRegion());
|
||||
return R.ok(config);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user