Springboot系列之接入腾讯云对象存储COS
Springboot-接入腾讯云对象存储COS
腾讯云存储
腾讯云对象存储(Tencent Cloud Object Storage,COS)是一种安全、可靠、低成本、高扩展的云端存储服务。COS能够存储各种非结构化数据,包括图片、视频、音频、文本等。COS支持标准的HTTP/HTTPS协议,可以通过API、SDK、控制台等方式进行数据的上传、下载和管理。COS还提供了数据保护、数据备份、数据恢复、数据传输加密等多项安全措施,确保用户数据的安全性和可靠性。COS还支持自动化、智能化的数据生命周期管理,帮助用户降低数据存储成本。COS是云计算领域中存储服务的重要组成部分,广泛应用于云存储、备份、归档、内容分发等场景
腾讯云对象存储COS初始化:
申请腾讯云账号、进行实名认证
开通对象存储COS服务,进入管理控制台
创建Bucket(管理控制台=》存储桶列表=》创建存储桶),选择公有读取(其他选择默认)
Bucket创建完成,可在存储桶列表进行管理
创建API秘钥:访问管理=》API秘钥管理,创建秘钥用于API访问(注意23.11.30起SecretKey只支持在创建的时候查看,需要在初始化的时候进行保存)
代码对接腾讯云COS
参考腾讯云对象存储API接口对接文档
对接腾讯云COS需要使用其请提供的SDK进行构建,通过调用请求完成操作。此处参考Java SDK快速入门
建议创建子用户,使用子用户秘钥(例如创建一个dev-COS子用户,构建子用户秘钥)进行访问(避免主账号秘钥泄露造成风险),腾讯云用户管理
Maven引入cos依赖
<!-- https://mvnrepository.com/artifact/com.qcloud/cos_api -->
<dependency>
<groupId>com.qcloud</groupId>
<artifactId>cos_api</artifactId>
<version>5.6.211</version>
</dependency>
测试网络联通
# 方式1:ping测试网络联通
ping cos.ap-guangzhou.myqcloud.com
PING gz.file.myqcloud.com (27.155.119.181): 56 data bytes
64 bytes from 27.155.119.181: icmp_seq=0 ttl=45 time=16.814 ms
64 bytes from 27.155.119.181: icmp_seq=1 ttl=45 time=16.858 ms
64 bytes from 27.155.119.181: icmp_seq=2 ttl=45 time=17.273 ms
64 bytes from 27.155.119.181: icmp_seq=3 ttl=45 time=16.924 ms
64 bytes from 27.155.119.181: icmp_seq=4 ttl=45 time=16.884 ms
64 bytes from 27.155.119.181: icmp_seq=5 ttl=45 time=17.422 ms
# 方式2:curl测试访问
// curl测试http访问
curl http://cos.ap-guangzhou.myqcloud.com -v
// curl测试https范文
curl https://cos.ap-guangzhou.myqcloud.com -vk
# 如果可以正常响应则说明访问正常
application.yml:配置腾讯云服务API密钥(secretId、secretKey)
考虑安全问题,如果是单独测试可考虑创建一个临时的访问凭据,避免密钥泄露导致不可预测的安全问题
# 腾讯云COS
txCloud:
dev-COS:
appId: xxx
secretId: xxxx
secretKey: xxxx
bucket: example-bucket
创建测试类测试腾讯云COS连接(获取所有存储桶信息)
import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.auth.BasicCOSCredentials;
import com.qcloud.cos.auth.COSCredentials;
import com.qcloud.cos.model.Bucket;
import com.qcloud.cos.region.Region;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
@SpringBootTest
public class TxCloudTest {
@Value("${txCloud.dev-COS.secretId}")
private String secretId;
@Value("${txCloud.dev-COS.secretKey}")
private String secretKey;
@Value("${txCloud.dev-COS.appId}")
private String appId;
@Value("${txCloud.dev-COS.bucket}")
private String bucket;
// cos客户端定义
private COSClient cosClient;
/**
* 测试腾讯云COS服务
*/
@Test
public void testGetBucket() {
// 初始化用户身份信息(secretId, secretKey)
COSCredentials cred = new BasicCOSCredentials(secretId,secretKey);
// 设置bucket的区域, COS地域的简称请参照 https://www.qcloud.com/document/product/436/6224
ClientConfig clientConfig = new ClientConfig(new Region("ap-guangzhou"));
// 生成cos客户端
COSClient cosClient = new COSClient(cred, clientConfig);
List<Bucket> buckets = cosClient.listBuckets();
for (Bucket bucketElement : buckets) {
String bucketName = bucketElement.getName();
String bucketLocation = bucketElement.getLocation();
System.out.println("存储桶"+bucketName+"-"+bucketLocation);
}
}
}
测试testGetBucket查看控制台打印相关的存储桶信息
1.创建桶
SpringbootTest,测试方法将创建COS客户端对象抽离出来,随后直接通过客户端对象访问COS
创建桶:需注意Bucket名称必须为小写(否则创建提示java.lang.IllegalArgumentException: Bucket name should not contain uppercase characters)
@SpringBootTest
public class TxCloudTest {
@Value("${txCloud.dev-COS.secretId}")
private String secretId;
@Value("${txCloud.dev-COS.secretKey}")
private String secretKey;
@Value("${txCloud.dev-COS.appId}")
private String appId;
@Value("${txCloud.dev-COS.bucket}")
private String bucket;
// cos客户端定义
private COSClient cosClient;
/**
* 初始化(每个测试方法执行前执行初始化)
*/
@BeforeEach
public void initClient(){
// 初始化用户身份信息(secretId, secretKey)
COSCredentials cred = new BasicCOSCredentials(secretId,secretKey);
// 设置bucket的区域, COS地域的简称请参照 https://www.qcloud.com/document/product/436/6224
ClientConfig clientConfig = new ClientConfig(new Region("ap-guangzhou"));
// 生成cos客户端
cosClient = new COSClient(cred, clientConfig);
}
/**
* 测试腾讯云COS服务
*/
@Test
public void testGetBucket() {
List<Bucket> buckets = cosClient.listBuckets();
for (Bucket bucketElement : buckets) {
String bucketName = bucketElement.getName();
String bucketLocation = bucketElement.getLocation();
System.out.println("存储桶:"+bucketName+"-"+bucketLocation);
}
}
/**
* 创建存储桶
*/
@Test
public void testCreateBucket() {
String bucketName = bucket + "-" + appId; // 存储桶名称,格式:Bucket-APPID
CreateBucketRequest createBucketRequest = new CreateBucketRequest(bucketName);
// 设置 bucket 的权限为 Private(私有读写), 其他可选有公有读私有写, 公有读写
createBucketRequest.setCannedAcl(CannedAccessControlList.Private);
Bucket bucketResult = cosClient.createBucket(createBucketRequest);
}
}
2.上传指定对象到桶中
将本地文件或者已知长度的输入流内容上传到 COS,适用于20M以下图片类小文件上传,最大支持上传不超过5GB文件。5GB以上的文件必须使用分块上传或高级 API 接口上传。(高级API接口在com.qcloud.cos.transfer.\*
子包下)
如果存在重复的key,则上传的时候会覆盖旧的对象,对象键(key)是对象在存储桶中的唯一标识(例如bucketName-AppId.cos.ap-guangzhou.myqcloud.com/folder/logo.jpg)
上传不超过5GB的文件参考示例:
/**
* 上传指定对象
*/
@Test
public void uploadObj(){
// 指定上传文件(例如此处上传一个照片)
String localFilePath = "/Users/xxxx/Desktop/mine/logo.jpg";
// 指定要上传的文件
File localFile = new File(localFilePath);
// 指定文件将要存放的存储桶
String bucketName = bucket + "-" + appId;
// 对象key(存储桶的唯一标识):指定文件上传到 COS 上的路径,即对象键。例如此处设定表示将文件 logo.jpg 上传到 folder 路径下
String key = "folder/logo.jpg";
PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, key, localFile);
// 执行文件上传操作
PutObjectResult putObjectResult = cosClient.putObject(putObjectRequest);
System.out.println(putObjectResult);
}
3.查询对象列表
查询对象列表数据
/**
* 查询对象列表
*/
@Test
public void getObj(){
// Bucket 的命名格式为 Bucket-APPID ,此处填写的存储桶名称必须为此格式
String bucketName = bucket + "-" + appId;
ListObjectsRequest listObjectsRequest = new ListObjectsRequest();
// 设置 bucket 名称
listObjectsRequest.setBucketName(bucketName);
// prefix 表示列出的 object 的 key 以 prefix 开始
listObjectsRequest.setPrefix("folder/");
// deliter 表示分隔符, 设置为/表示列出当前目录下的 object, 设置为空表示列出所有的 object
listObjectsRequest.setDelimiter("/");
// 设置最大遍历出多少个对象, 一次 listobject 最大支持1000
listObjectsRequest.setMaxKeys(1000);
ObjectListing objectListing = null;
do {
try {
objectListing = cosClient.listObjects(listObjectsRequest);
} catch (CosServiceException e) {
e.printStackTrace();
return;
} catch (CosClientException e) {
e.printStackTrace();
return;
}
// common prefix 表示被 delimiter 截断的路径, 如 delimter 设置为/, common prefix 则表示所有子目录的路径
List<String> commonPrefixs = objectListing.getCommonPrefixes();
// object summary 表示所有列出的 object 列表
List<COSObjectSummary> cosObjectSummaries = objectListing.getObjectSummaries();
for (COSObjectSummary cosObjectSummary : cosObjectSummaries) {
// 文件的路径 key
String key = cosObjectSummary.getKey();
// 文件的 etag
String etag = cosObjectSummary.getETag();
// 文件的长度
long fileSize = cosObjectSummary.getSize();
// 文件的存储类型
String storageClasses = cosObjectSummary.getStorageClass();
System.out.println("对象:" + key);
}
String nextMarker = objectListing.getNextMarker();
listObjectsRequest.setMarker(nextMarker);
} while (objectListing.isTruncated());
}
4.下载对象
下载对象有两种方式:获取下载对象的CRC64(对象流)、直接下载到本地
/**
* 下载对象(方式1)
*/
@Test
public void downloadObj01() throws IOException {
// Bucket 的命名格式为 BucketName-APPID ,此处填写的存储桶名称必须为此格式
String bucketName = bucket + "-" + appId;
// 指定文件在 COS 上的路径(对象键)例如对象键为 folder/logo.jpg,则表示下载的文件 logo.jpg 在 folder 路径下
String key = "folder/logo.jpg";
// 获取下载输入流
GetObjectRequest getObjectRequest = new GetObjectRequest(bucketName, key);
COSObject cosObject = cosClient.getObject(getObjectRequest);
COSObjectInputStream cosObjectInput = cosObject.getObjectContent();
// 下载对象的 CRC64
String crc64Ecma = cosObject.getObjectMetadata().getCrc64Ecma();
System.out.println("对象流:" + crc64Ecma);
// 关闭输入流
cosObjectInput.close();
}
/**
* 下载对象(方式2)
*/
@Test
public void downloadObj02(){
// Bucket 的命名格式为 Bucket-APPID ,此处填写的存储桶名称必须为此格式
String bucketName = bucket + "-" + appId;
// 指定文件在 COS 上的路径(对象键)例如对象键为 folder/logo.jpg,则表示下载的文件 logo.jpg 在 folder 路径下
String key = "folder/logo.jpg";
// 下载文件到本地的路径,例如 把文件下载到本地的指定路径下的文件夹中(指定下载对象)
GetObjectRequest getObjectRequest = new GetObjectRequest(bucketName, key);
String outputFilePath = "/Users/holic-x/Desktop/mine/newLogo.jpg";
File downFile = new File(outputFilePath);
getObjectRequest = new GetObjectRequest(bucketName, key);
ObjectMetadata downObjectMeta = cosClient.getObject(getObjectRequest, downFile);
}
5.删除对象
/**
* 删除对象(根据key值删除指定对象)
*/
@Test
public void delObj(){
// Bucket 的命名格式为 BucketName-APPID ,此处填写的存储桶名称必须为此格式
String bucketName = "example-bucket-" + appId;
String key = "folder/logo.jpg";
cosClient.deleteObject(bucketName, key);
}
6.删除桶
/**
* 删除桶
*/
@Test
public void delBucket(){
// Bucket 的命名格式为 BucketName-APPID ,此处填写的存储桶名称必须为此格式
String bucketName = "example-bucket-" + appId;
cosClient.deleteBucket(bucketName);
}
需注意,存储桶的权限开放,如果默认是私有读写,则上传的文件会带sign后缀,直接通过url不允许方法
如果希望通过url访问,访问失败则考虑是否开设了访问权限,其次就算开设了存储桶访问权限,一些通过私有读写上传的文件也是不能直接访问的(需要设定sign签名认证通过之后才可以访问);其次确认是否设定了防盗链。(如果设定防盗链,则不允许直接访问图片url)
针对域名映射,如果不希望存储桶信息暴露在外部,则可创建域名进行映射,进而隐藏真正的存储桶信息,保护个人系统
文件上传后端处理:
- 结合腾讯云cos 需要将上传的文件进行暂存(有多种方式,最基础的就是先暂存到一个地方然后等到对接cos完毕之后再清理临时文件。或者借助第三方工具进行构建)
文件上传前端的现存问题:
通过action上传不带cookie(参考bi智能分析相关内容,文件上传部分看是如何处理)
customRequest(无法带指定参数),没有可行案例,待定