1、导入相关依赖
<!--腾讯云COS--><dependency><groupId>com.tencentcloudapi</groupId><artifactId>tencentcloud-sdk-java</artifactId><version>3.0.1</version></dependency><dependency><groupId>com.qcloud</groupId><artifactId>cos_api</artifactId><version>5.6.8</version></dependency>
2、编写配置类,获取配置信息
创建配置类主要需要以下信息
腾讯云账号秘钥和密码秘钥:用于创建COSClient链接对象,识别用户身份信息
存储桶区域:需要设置客户端所属区域Region
存储桶名称:创建请求时,需要告知上传到哪个存储桶下
存储桶访问路径:用于拼装上传文件完整访问路径
我获得的信息均写在配置类中,这里使用 @Value 或者 @ConfigurationProperties 都可以,写法就不多说,但是注意 @ConfigurationProperties 支持松散绑定,在识别读取配置信息时,不区分大小写,且会去掉中划线-、下划线_ (A-b_Obj→abobj→abObj),参考:SpringBoot松散绑定(宽松绑定)@ConfigurationProperties
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.region.Region;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;/*** @author phf* @description @ConfigurationProperties 松散绑定(中划线-、下划线_ 都去掉,且不区分大小写)*/
@Component
@ConfigurationProperties(prefix = "cos")
@Data
public class CosConfig {/*** 腾讯云账号秘钥*/private String secretId;/*** 密码秘钥*/private String secretKey;/*** 存储桶地区*/private String region;/*** 存储桶名称*/private String bucketName;/*** 存储桶访问路径*/private String path;/*** 初始化cos对象,配置相关配置信息*/@Beanpublic COSClient cosClient(){// 1 初始化用户身份信息(secretId, secretKey)。COSCredentials cred = new BasicCOSCredentials(this.secretId, this.secretKey);// 2 设置 bucket 的区域Region region = new Region(this.region);ClientConfig clientConfig = new ClientConfig(region);// 3 生成 cos 客户端。COSClient cosClient = new COSClient(cred, clientConfig);return cosClient;}
}
配置信息获取
(1)进入腾讯云对象存储→创建存储桶(有则跳过),获取存储桶名称、区域、存储桶访问路径
(2)获取腾讯云账号秘钥
3、编写逻辑层——实现上传
我这里用了多文件上传,单文件上传,把数组和循环去掉即可
public interface ICosFileService {/*** 上传* @param files* @return*/RestApiResponse<String> upload(MultipartFile[] files);/*** 删除* @param fileName* @return*/RestApiResponse<Void> delete(String fileName);
}
@Slf4j
@Service
public class ICosFileServiceImpl implements ICosFileService {@Resourceprivate COSClient cosClient;@Resourceprivate CosConfig cosConfig;@Override@Transactional(rollbackFor = Exception.class)public RestApiResponse<String> upload(MultipartFile[] files) {RestApiResponse<String> response = RestApiResponse.success();String res = "";try {for (MultipartFile file : files) {String originalFileName = file.getOriginalFilename();// 获得文件流InputStream inputStream = null;inputStream = file.getInputStream();// 设置文件路径String filePath = getFilePath(originalFileName, "你的桶内文件路径abc/def/test/");// 上传文件String bucketName = cosConfig.getBucketName();ObjectMetadata objectMetadata = new ObjectMetadata();objectMetadata.setContentLength(file.getSize());objectMetadata.setContentType(file.getContentType());PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, filePath, inputStream, objectMetadata);cosClient.putObject(putObjectRequest);cosClient.setBucketAcl(bucketName, CannedAccessControlList.PublicRead);String url = cosConfig.getPath() + "/" + filePath;res += url + ",";}String paths = res.substring(0, res.length() - 1);response.setData(paths);return response;} catch (IOException e) {e.printStackTrace();} finally {cosClient.shutdown();}return RestApiResponse.fail();}@Overridepublic RestApiResponse<Void> delete(String fileName) {cosConfig.cosClient();// 文件桶内路径String filePath = getDelFilePath(fileName, "你的桶内文件路径abc/def/test/");cosClient.deleteObject(cosConfig.getBucketName(), filePath);return RestApiResponse.success();}/*** 生成文件路径* @param originalFileName 原始文件名称* @param folder 存储路径* @return*/private String getFilePath(String originalFileName, String folder) {// 获取后缀名String fileType = originalFileName.substring(originalFileName.lastIndexOf("."));// 以文件后缀来存储在存储桶中生成文件夹方便管理String filePath = folder + "/";// 去除文件后缀 替换所有特殊字符String fileStr = StrUtil.removeSuffix(originalFileName, fileType).replaceAll("[^0-9a-zA-Z\\u4e00-\\u9fa5]", "_");filePath += new DateTime().toString("yyyyMMddHHmmss") + "_" + fileStr + fileType;log.info("filePath:" + filePath);return filePath;}/*** 生成文件路径* @param originalFileName 原始文件名称* @param folder 存储路径* @return*/private String getDelFilePath(String originalFileName, String folder) {// 获取后缀名String fileType = originalFileName.substring(originalFileName.lastIndexOf("."));// 以文件后缀来存储在存储桶中生成文件夹方便管理String filePath = folder + "/";// 去除文件后缀 替换所有特殊字符String fileStr = StrUtil.removeSuffix(originalFileName, fileType).replaceAll("[^0-9a-zA-Z\\u4e00-\\u9fa5]", "_");filePath += fileStr + fileType;log.info("filePath:" + filePath);return filePath;}
}
4、编写Controller测试
@Api(tags = "cos文件操作")
@RestController
@RequestMapping("/cos")
public class ICosFileController {@Autowiredprivate ICosFileService iCosFileService;@ApiOperation(value = "文件上传", httpMethod = "POST")@PostMapping("/upload")public RestApiResponse<String> upload(@RequestParam("files") MultipartFile[] files) {RestApiResponse<String> result = iCosFileService.upload(files);return result;}@ApiOperation(value = "文件删除", httpMethod = "POST")@PostMapping("/delete")public RestApiResponse<String> delete(@RequestParam("fileName") String fileName) {iCosFileService.delete(fileName);return RestApiResponse.success();}
}
上传成功,且返回完整信息
删除时,保证删除的文件名称参数key,为桶内文件完整路径即可,如果你的桶是app-bucket-name,文件含桶路径是app-bucket-name/file1/file2/file.png,那桶内完整路径就是file1/file2/file.png
public RestApiResponse<Void> delete(String fileName) {cosConfig.cosClient();// 文件桶内路径String filePath = getDelFilePath(fileName, "你的桶内文件路径abc/def/test/");// 这里的第二个参数,必须是桶内的完整路径cosClient.deleteObject(cosConfig.getBucketName(), filePath);return RestApiResponse.success();}
5、问题:COSClient报错连接池已关闭
之前自主调用了cosClient.shutdown,结果第二次上传时,就抛出异常,其实它自己维护了一个线程池:对象存储 Java SDK 常见问题-SDK 文档-文档中心-腾讯云
6、完整代码
https://download.csdn.net/download/huofuman960209/88085303