1.pom.xml中添加cos配置
XML
<!--腾讯cos -->
<dependency>
<groupId>com.qcloud</groupId>
<artifactId>cos_api</artifactId>
<version>5.6.28</version>
</dependency>
2.application.yaml中添加cos配置
java
# 腾讯云存储cos相关公共配置
tencent:
cos:
secretId: ABIDFG5gz36gMp2xbyHvYw3u
secretKey: 93ima8OcaHhDUUDjEdmfYEd
bucketName: haha-18888888
folder: video
region: ap-shanghai
3.创建属性映射类CosProperties
java
/**
* Cos配置
*/
@Data
@Component
@RefreshScope
@ConfigurationProperties(prefix = "tencent.cos")
public class CosProperties {
private String secretId;
private String secretKey;
private String bucketName;
private String folder;
private String region;
}
4.封装Cos工具类
java
/**
* cos 工具类
*/
@Slf4j
public class CosUtils {
private static CosUtils cosUtils = new CosUtils();
private COSClient cosClient;
public static CosUtils getInstance() {
return cosUtils;
}
private CosProperties cosProperties;
public CosUtils setCosProperties(CosProperties cosProperties) {
this.cosProperties = cosProperties;
this.cosClient = createCOSClient(cosProperties);
return this;
}
public String getUploadTemporaryToken(String key) {
if (StrUtil.hasBlank(cosProperties.getSecretId(), cosProperties.getSecretKey())) {
return null;
}
COSCredentials cred = new BasicCOSCredentials(cosProperties.getSecretId(), cosProperties.getSecretKey());
COSSigner signer = new COSSigner();
// 设置过期时间为1个小时
LocalDateTime now = LocalDateTime.now();
Date expiredTime = new Date(now.toInstant(ZoneOffset.of("+8")).toEpochMilli() + 3600L * 1000L);
// 要签名的 key, 生成的签名只能用于对应此 key 的上传
log.info("待签名key[{}], now[{}]", key, now);
String signStr = signer.buildAuthorizationStr(HttpMethodName.PUT, key, cred, expiredTime);
log.info("签名成功, key[{}], now[{}], signStr[{}]", key, now, signStr);
return signStr;
}
/**
* 上传文件
* 1.创建本地文件 2.上传
*
* @param fileName 文件名(带后缀)
* @param fileContent 文件内容
* @return
*/
public String upload(String fileName, String fileContent, String customizeFolder) {
try {
String cosSecretId = cosProperties.getSecretId();
String cosSecretKey = cosProperties.getSecretKey();
String folder = StringUtils.isEmpty(customizeFolder) ? cosProperties.getFolder() : customizeFolder;
String bucketName = cosProperties.getBucketName();
if (StringUtils.isEmpty(cosSecretId) ||
StringUtils.isEmpty(cosSecretKey) ||
StringUtils.isEmpty(bucketName) ||
StringUtils.isEmpty(folder)) {
log.error("cos upload params Incomplete");
return "";
}
String root = Objects.requireNonNull(CosUtils.class.getResource("/")).getPath();
String s = root + "/temp/upload/";
File localFile = getLocalFile(fileContent, s, fileName);
if (localFile == null) {
return "";
}
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
String fromatDate = LocalDateTime.now().format(formatter);
String fileUrl = folder + "/" + fromatDate + "/" + fileName;
PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, fileUrl, localFile);
// 设置存储类型, 默认是标准(Standard), 低频(standard_ia)
putObjectRequest.setStorageClass(StorageClass.Standard);
try {
this.cosClient.putObject(putObjectRequest);
} catch (CosClientException e) {
log.error("An exception occurs during execution cos upload,error message:{}", e.getMessage());
}
//删除本地缓存文件
if (localFile.exists()) {
localFile.delete();
}
return fileUrl.startsWith("/") ? fileUrl : "/" + fileUrl;
}catch (Exception e){
log.error("文件上传失败,{}",e);
}
return StrUtil.EMPTY;
}
/**
* 删除文件
*
* @param bucketName
* @param key
* @return
*/
public Boolean deleteCosFile(String bucketName, String key) {
String cosSecretId = cosProperties.getSecretId();
String cosSecretKey = cosProperties.getSecretKey();
Boolean executeFlag = true;
if (StringUtils.isEmpty(cosSecretId) ||
StringUtils.isEmpty(cosSecretKey) ||
StringUtils.isEmpty(bucketName) ||
StringUtils.isEmpty(key)) {
log.error("cos delete file params Incomplete");
return false;
}
COSCredentials cred = new BasicCOSCredentials(cosSecretId, cosSecretKey);
// 2 设置bucket的区域, COS地域的简称请参照 https://www.qcloud.com/document/product/436/6224
ClientConfig clientConfig = new ClientConfig(new Region("ap-nanjing"));
// 3 生成cos客户端
COSClient cosclient = new COSClient(cred, clientConfig);
try {
cosclient.deleteObject(bucketName, key);
} catch (CosClientException e) {
log.error("An exception occurs during execution cos delete,error message:{}", e.getMessage());
executeFlag = false;
}
// 关闭客户端
cosclient.shutdown();
return executeFlag;
}
private void getDir(String path) {
File localFile = new File(path);
if (!localFile.exists()) {
localFile.mkdirs();
}
}
private File getLocalFile(String instructionSet, String dir, String fileName) {
File localFile = null;
try {
getDir(dir);
localFile = new File(dir, fileName);
if (!localFile.exists()) {
localFile.createNewFile();
}
FileOutputStream fos = new FileOutputStream(localFile, true);
OutputStreamWriter osw = new OutputStreamWriter(fos);
BufferedWriter bw = new BufferedWriter(osw);
bw.write(instructionSet);
bw.newLine();
bw.flush();
bw.close();
osw.close();
fos.close();
return localFile;
} catch (IOException e2) {
log.error("An exception occurs during execution create local file,error message:{} ", e2.getMessage());
return null;
}
}
/**
* 获取二进制文件
*/
public static byte[] downLoadBinary(String urlStr) throws IOException {
HttpURLConnection conn = null;
InputStream inputStream = null;
ByteArrayOutputStream bos = null;
try {
URL url = new URL(urlStr);
conn = (HttpURLConnection) url.openConnection();
//设置超时间为10秒
conn.setConnectTimeout(10 * 1000);
conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.135 Safari/537.36");
//得到输入流
inputStream = conn.getInputStream();
bos = new ByteArrayOutputStream();
//获取数据数组
return readInputStream(inputStream, bos);
} finally {
if (bos != null) {
bos.close();
}
if (inputStream != null) {
inputStream.close();
}
if (conn != null) {
conn.disconnect();
}
}
}
/**
* 获取字符串列表
*/
public static List<String> downLoadList(String urlStr) throws IOException {
HttpURLConnection conn = null;
InputStream inputStream = null;
try {
URL url = new URL(urlStr);
conn = (HttpURLConnection) url.openConnection();
//设置超时间为10秒
conn.setConnectTimeout(10 * 1000);
conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.135 Safari/537.36");
//得到输入流
inputStream = conn.getInputStream();
//获取数据数组 windows操作系统默认编码:GB18030
return IoUtil.readLines(new InputStreamReader(inputStream, Charset.forName("GB18030")), new ArrayList<>());
} catch (IOException e){
log.error("An exception occurs during execution download file,error message:{} ", e.getMessage());
return Collections.EMPTY_LIST;
}finally {
if (inputStream != null) {
inputStream.close();
}
if (conn != null) {
conn.disconnect();
}
}
}
/**
* 输入流转二进制
*/
public static byte[] readInputStream(InputStream inputStream, ByteArrayOutputStream bos) throws IOException {
byte[] buffer = new byte[1024];
int len = 0;
while ((len = inputStream.read(buffer)) != -1) {
bos.write(buffer, 0, len);
}
return bos.toByteArray();
}
/**
* 创建cosClient
*
* @param cosProperties
* @return
*/
public static COSClient createCOSClient(CosProperties cosProperties) {
// 1 初始化用户身份信息(secretId, secretKey)。
// SECRETID和SECRETKEY请登录访问管理控制台 https://console.cloud.tencent.com/cam/capi
// 进行查看和管理
String secretId = cosProperties.getSecretId();
String secretKey = cosProperties.getSecretKey();
COSCredentials cred = new BasicCOSCredentials(secretId, secretKey);
// 2 设置 bucket 的地域, COS 地域的简称请参照
// https://cloud.tencent.com/document/product/436/6224
// clientConfig 中包含了设置 region, https(默认 http), 超时, 代理等 set 方法, 使用可参见源码或者常见问题
// Java SDK 部分。
Region region = new Region(cosProperties.getRegion());
ClientConfig clientConfig = new ClientConfig(region);
// 这里建议设置使用 https 协议
// 从 5.6.54 版本开始,默认使用了 https
clientConfig.setHttpProtocol(HttpProtocol.https);
// 3 生成 cos 客户端。
return new COSClient(cred, clientConfig);
}
/**
* 获取视频属性: (宽度、高度、时长)
* 获取方式:从oss获取
*
* @param ossUrl
* @return
*/
public VideoProperties getVideoPropertiesFromCos(String ossUrl) {
try {
// 此处的key为对象键,对象键是对象在存储桶内的唯一标识
String key = ossUrl;
GeneratePresignedUrlRequest req = new GeneratePresignedUrlRequest("greatpan-1300159541", key, HttpMethodName.GET);
// 设置签名过期时间(可选), 若未进行设置, 则默认使用 ClientConfig 中的签名过期时间(1小时)
// 可以设置任意一个未来的时间,推荐是设置 10 分钟到 3 天的过期时间
// 这里设置签名在半个小时后过期
Date expirationDate = new Date(System.currentTimeMillis() + 30L * 60L * 1000L);
req.setExpiration(expirationDate);
req.addRequestParameter("ci-process", "videoinfo");
URL url = this.cosClient.generatePresignedUrl(req);
String mediaInfoXml = HttpClientUtil.doGet(url.toString());
if (mediaInfoXml != null) {
Document document = XmlUtil.readXML(mediaInfoXml);
Node error = document.getElementsByTagName("Error").item(0);
if (!ObjectUtils.isEmpty(error)) {
Node message = document.getElementsByTagName("Message").item(0);
log.error("获取视频基础信息出错.ossurl:{}, e:{}", ossUrl, Optional.ofNullable(message).map(Node::getTextContent).orElse(""));
return null;
}
String width = document.getElementsByTagName("Width").item(0).getTextContent();
String height = document.getElementsByTagName("Height").item(0).getTextContent();
String rotation = document.getElementsByTagName("Rotation").item(0).getTextContent();
if (StringUtils.isEmpty(width) || StringUtils.isEmpty(height) || StringUtils.isEmpty(rotation)) {
return null;
}
VideoProperties videoProperties = new VideoProperties();
int w = Integer.parseInt(width);
int h = Integer.parseInt(height);
int r = (int) Double.parseDouble(rotation);
// 如果r是90或者270, 说明视频有旋转操作, 并宽高比有变化,需要把w 和 h 调换
if (r % 90 == 0 && (r / 90 % 2) == 1) {
videoProperties.setHeight(w);
videoProperties.setWidth(h);
return videoProperties;
}
videoProperties.setHeight(h);
videoProperties.setWidth(w);
return videoProperties;
}
return null;
} catch (Exception e) {
log.error("获取视频基础信息出错.ossurl:{}, e:", ossUrl, e);
return null;
}
}
public static void main(String[] args) throws Exception {
// VideoProperties videoPropertiesFromCos = getVideoPropertiesFromCos("/video/2024-05-30/723d5de3-f874-4744-819f-0a31e6e8e507.mp4");
// System.out.println(videoPropertiesFromCos);
byte[] bytes = CosUtils.downLoadBinary("http://fs.haha.com/video/2024-05-30/1484098659191754752.txt");
System.out.println(new String(bytes));
}
}
5.前端获取cos上传token
java
@Resource
private CosUtils cosUtils;
@GetMapping("/token")
@ApiOperation("获取文件存储token")
public ApiResponse<?> getFileUploadToken(@RequestParam String fileFullPath) {
if(StringUtils.isEmpty(fileFullPath)){
return ApiResponse.error("参数错误");
}
return ApiResponse.ok(cosUtils.getUploadTemporaryToken(fileFullPath));
}