From 9f7f4c45641335e5909e8002feaad035aa222a36 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=86=B7=E5=86=B7?= <2270033969@qq.com>
Date: Mon, 10 Mar 2025 13:01:53 +0800
Subject: [PATCH] =?UTF-8?q?feat(oss):=20=E6=B7=BB=E5=8A=A0=20`skipMd5Check?=
=?UTF-8?q?`=20=E9=85=8D=E7=BD=AE=E9=A1=B9=E4=BB=A5=E6=94=AF=E6=8C=81?=
=?UTF-8?q?=E8=B7=B3=E8=BF=87=20MD5=20=E6=A3=80=E6=9F=A5?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
#6272 使用腾讯云存储COS ,图片不能正常下载的问题, Invalid base 16 character: '"'
---
.../pigx/common/file/oss/OssProperties.java | 73 +--
.../common/file/oss/service/OssTemplate.java | 416 +++++++++---------
2 files changed, 252 insertions(+), 237 deletions(-)
diff --git a/pigx-common/pigx-common-oss/src/main/java/com/pig4cloud/pigx/common/file/oss/OssProperties.java b/pigx-common/pigx-common-oss/src/main/java/com/pig4cloud/pigx/common/file/oss/OssProperties.java
index 6539304ab..3e2682c0f 100755
--- a/pigx-common/pigx-common-oss/src/main/java/com/pig4cloud/pigx/common/file/oss/OssProperties.java
+++ b/pigx-common/pigx-common-oss/src/main/java/com/pig4cloud/pigx/common/file/oss/OssProperties.java
@@ -35,46 +35,51 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "oss")
public class OssProperties {
- /**
- * 对象存储服务的URL
- */
- private String endpoint;
+ /**
+ * 对象存储服务的URL
+ */
+ private String endpoint;
- /**
- * 自定义域名
- */
- private String customDomain;
+ /**
+ * 自定义域名
+ */
+ private String customDomain;
- /**
- * true path-style nginx 反向代理和S3默认支持 pathStyle {http://endpoint/bucketname} false
- * supports virtual-hosted-style 阿里云等需要配置为 virtual-hosted-style
- * 模式{http://bucketname.endpoint}
- */
- private Boolean pathStyleAccess = true;
+ /**
+ * true path-style nginx 反向代理和S3默认支持 pathStyle {http://endpoint/bucketname} false
+ * supports virtual-hosted-style 阿里云等需要配置为 virtual-hosted-style
+ * 模式{http://bucketname.endpoint}
+ */
+ private Boolean pathStyleAccess = true;
- /**
- * 应用ID
- */
- private String appId;
+ /**
+ * 应用ID
+ */
+ private String appId;
- /**
- * 区域
- */
- private String region;
+ /**
+ * 区域
+ */
+ private String region;
- /**
- * Access key就像用户ID,可以唯一标识你的账户
- */
- private String accessKey;
+ /**
+ * Access key就像用户ID,可以唯一标识你的账户
+ */
+ private String accessKey;
- /**
- * Secret key是你账户的密码
- */
- private String secretKey;
+ /**
+ * Secret key是你账户的密码
+ */
+ private String secretKey;
- /**
- * 最大线程数,默认: 100
- */
- private Integer maxConnections = 100;
+ /**
+ * 最大线程数,默认: 100
+ */
+ private Integer maxConnections = 100;
+
+ /**
+ * 跳过 MD5 检查
+ */
+ private boolean skipMd5Check;
}
diff --git a/pigx-common/pigx-common-oss/src/main/java/com/pig4cloud/pigx/common/file/oss/service/OssTemplate.java b/pigx-common/pigx-common-oss/src/main/java/com/pig4cloud/pigx/common/file/oss/service/OssTemplate.java
index 4afc2fd8e..63bfab419 100755
--- a/pigx-common/pigx-common-oss/src/main/java/com/pig4cloud/pigx/common/file/oss/service/OssTemplate.java
+++ b/pigx-common/pigx-common-oss/src/main/java/com/pig4cloud/pigx/common/file/oss/service/OssTemplate.java
@@ -17,7 +17,7 @@
package com.pig4cloud.pigx.common.file.oss.service;
-import cn.hutool.core.text.CharPool;
+import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.amazonaws.ClientConfiguration;
import com.amazonaws.auth.AWSCredentials;
@@ -52,226 +52,236 @@ import java.util.*;
@RequiredArgsConstructor
public class OssTemplate implements InitializingBean, FileTemplate {
- private final FileProperties properties;
+ private final FileProperties properties;
- private AmazonS3 amazonS3;
+ private AmazonS3 amazonS3;
- /**
- * 创建bucket
- * @param bucketName bucket名称
- */
- @SneakyThrows
- public void createBucket(String bucketName) {
- if (!amazonS3.doesBucketExistV2(bucketName)) {
- amazonS3.createBucket((bucketName));
- }
- }
+ /**
+ * 创建bucket
+ *
+ * @param bucketName bucket名称
+ */
+ @SneakyThrows
+ public void createBucket(String bucketName) {
+ if (!amazonS3.doesBucketExistV2(bucketName)) {
+ amazonS3.createBucket((bucketName));
+ }
+ }
- /**
- * 获取全部bucket
- *
- *
- * @see AWS
- * API Documentation
- */
- @SneakyThrows
- public List getAllBuckets() {
- return amazonS3.listBuckets();
- }
+ /**
+ * 获取全部bucket
+ *
+ *
+ * @see AWS
+ * API Documentation
+ */
+ @SneakyThrows
+ public List getAllBuckets() {
+ return amazonS3.listBuckets();
+ }
- /**
- * @param bucketName bucket名称
- * @see AWS
- * API Documentation
- */
- @SneakyThrows
- public Optional getBucket(String bucketName) {
- return amazonS3.listBuckets().stream().filter(b -> b.getName().equals(bucketName)).findFirst();
- }
+ /**
+ * @param bucketName bucket名称
+ * @see AWS
+ * API Documentation
+ */
+ @SneakyThrows
+ public Optional getBucket(String bucketName) {
+ return amazonS3.listBuckets().stream().filter(b -> b.getName().equals(bucketName)).findFirst();
+ }
- /**
- * @param bucketName bucket名称
- * @see AWS API
- * Documentation
- */
- @SneakyThrows
- public void removeBucket(String bucketName) {
- amazonS3.deleteBucket(bucketName);
- }
+ /**
+ * @param bucketName bucket名称
+ * @see AWS API
+ * Documentation
+ */
+ @SneakyThrows
+ public void removeBucket(String bucketName) {
+ amazonS3.deleteBucket(bucketName);
+ }
- /**
- * 根据文件前置查询文件
- * @param bucketName bucket名称
- * @param prefix 前缀
- * @param recursive 是否递归查询
- * @return S3ObjectSummary 列表
- * @see AWS
- * API Documentation
- */
- @SneakyThrows
- public List getAllObjectsByPrefix(String bucketName, String prefix, boolean recursive) {
- ObjectListing objectListing = amazonS3.listObjects(bucketName, prefix);
- return new ArrayList<>(objectListing.getObjectSummaries());
- }
+ /**
+ * 根据文件前置查询文件
+ *
+ * @param bucketName bucket名称
+ * @param prefix 前缀
+ * @param recursive 是否递归查询
+ * @return S3ObjectSummary 列表
+ * @see AWS
+ * API Documentation
+ */
+ @SneakyThrows
+ public List getAllObjectsByPrefix(String bucketName, String prefix, boolean recursive) {
+ ObjectListing objectListing = amazonS3.listObjects(bucketName, prefix);
+ return new ArrayList<>(objectListing.getObjectSummaries());
+ }
- /**
- * 获取文件外链
- * @param bucketName bucket名称
- * @param objectName 文件名称
- * @param expires 过期时间 <=7
- * @return url
- * @see AmazonS3#generatePresignedUrl(String bucketName, String key, Date expiration)
- */
- @SneakyThrows
- public String getObjectURL(String bucketName, String objectName, Integer expires) {
- Date date = new Date();
- Calendar calendar = new GregorianCalendar();
- calendar.setTime(date);
- calendar.add(Calendar.DAY_OF_MONTH, expires);
- URL url = amazonS3.generatePresignedUrl(bucketName, objectName, calendar.getTime());
- return url.toString();
- }
+ /**
+ * 获取文件外链
+ *
+ * @param bucketName bucket名称
+ * @param objectName 文件名称
+ * @param expires 过期时间 <=7
+ * @return url
+ * @see AmazonS3#generatePresignedUrl(String bucketName, String key, Date expiration)
+ */
+ @SneakyThrows
+ public String getObjectURL(String bucketName, String objectName, Integer expires) {
+ Date date = new Date();
+ Calendar calendar = new GregorianCalendar();
+ calendar.setTime(date);
+ calendar.add(Calendar.DAY_OF_MONTH, expires);
+ URL url = amazonS3.generatePresignedUrl(bucketName, objectName, calendar.getTime());
+ return url.toString();
+ }
- /**
- * 获取文件
- * @param bucketName bucket名称
- * @param objectName 文件名称
- * @return 二进制流
- * @see AWS
- * API Documentation
- */
- @SneakyThrows
- public S3Object getObject(String bucketName, String objectName) {
- return amazonS3.getObject(bucketName, objectName);
- }
+ /**
+ * 获取文件
+ *
+ * @param bucketName bucket名称
+ * @param objectName 文件名称
+ * @return 二进制流
+ * @see AWS
+ * API Documentation
+ */
+ @SneakyThrows
+ public S3Object getObject(String bucketName, String objectName) {
+ if (properties.getOss().isSkipMd5Check()) {
+ System.setProperty("com.amazonaws.services.s3.disableGetObjectMD5Validation", "false");
+ }
+ return amazonS3.getObject(bucketName, objectName);
+ }
- /**
- * 获取文件
- * @param bucketName bucket名称
- * @param dir 文件夹名称
- * @param objectName 文件名称
- * @return 二进制流 API Documentation
- */
- @Override
- public S3Object getObject(String bucketName, String dir, String objectName) {
- if (StrUtil.isNotBlank(dir)) {
- objectName = dir + CharPool.SLASH + objectName;
- }
- return getObject(bucketName, objectName);
- }
+ /**
+ * 获取文件
+ *
+ * @param bucketName bucket名称
+ * @param dir 文件夹名称
+ * @param objectName 文件名称
+ * @return 二进制流 API Documentation
+ */
+ @Override
+ public S3Object getObject(String bucketName, String dir, String objectName) {
+ if (StrUtil.isNotBlank(dir)) {
+ objectName = dir + FileUtil.FILE_SEPARATOR + objectName;
+ }
+ return getObject(bucketName, objectName);
+ }
- /**
- * 上传文件
- * @param bucketName bucket名称
- * @param objectName 文件名称
- * @param stream 文件流
- * @throws Exception
- */
- public void putObject(String bucketName, String objectName, InputStream stream) throws Exception {
- putObject(bucketName, objectName, stream, stream.available(), "application/octet-stream");
- }
+ /**
+ * 上传文件
+ *
+ * @param bucketName bucket名称
+ * @param objectName 文件名称
+ * @param stream 文件流
+ * @throws Exception
+ */
+ public void putObject(String bucketName, String objectName, InputStream stream) throws Exception {
+ putObject(bucketName, objectName, stream, stream.available(), "application/octet-stream");
+ }
- /**
- * 上传文件
- * @param bucketName bucket名称
- * @param objectName 文件名称
- * @param stream 文件流
- * @param contextType 文件类型
- * @throws Exception
- */
- public void putObject(String bucketName, String objectName, InputStream stream, String contextType)
- throws Exception {
- putObject(bucketName, objectName, stream, stream.available(), contextType);
- }
+ /**
+ * 上传文件
+ *
+ * @param bucketName bucket名称
+ * @param objectName 文件名称
+ * @param stream 文件流
+ * @param contextType 文件类型
+ * @throws Exception
+ */
+ public void putObject(String bucketName, String objectName, InputStream stream, String contextType)
+ throws Exception {
+ putObject(bucketName, objectName, stream, stream.available(), contextType);
+ }
- /**
- * 上传文件
- * @param bucketName bucket名称
- * @param dir 文件夹名称
- * @param objectName 文件名称
- * @param stream 文件流
- * @param contextType 文件类型
- * @throws Exception
- */
- @Override
- public void putObject(String bucketName, String dir, String objectName, InputStream stream, String contextType)
- throws Exception {
- if (StrUtil.isNotBlank(dir)) {
- // dir 路径为 a/b
- objectName = dir + CharPool.SLASH + objectName;
- }
+ /**
+ * 上传文件
+ *
+ * @param bucketName bucket名称
+ * @param dir 文件夹名称
+ * @param objectName 文件名称
+ * @param stream 文件流
+ * @param contextType 文件类型
+ * @throws Exception
+ */
+ @Override
+ public void putObject(String bucketName, String dir, String objectName, InputStream stream, String contextType)
+ throws Exception {
+ if (StrUtil.isNotBlank(dir)) {
+ // dir 路径为 a/b
+ objectName = dir + FileUtil.FILE_SEPARATOR + objectName;
+ }
- putObject(bucketName, objectName, stream, stream.available(), contextType);
- }
+ putObject(bucketName, objectName, stream, stream.available(), contextType);
+ }
- /**
- * 上传文件
- * @param bucketName bucket名称
- * @param objectName 文件名称
- * @param stream 文件流
- * @param size 大小
- * @param contextType 类型
- * @throws Exception
- * @see AWS
- * API Documentation
- */
- public PutObjectResult putObject(String bucketName, String objectName, InputStream stream, long size,
- String contextType) throws Exception {
- // String fileName = getFileName(objectName);
- byte[] bytes = IOUtils.toByteArray(stream);
- ObjectMetadata objectMetadata = new ObjectMetadata();
- objectMetadata.setContentLength(size);
- objectMetadata.setContentType(contextType);
- ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
- // 上传
- return amazonS3.putObject(bucketName, objectName, byteArrayInputStream, objectMetadata);
+ /**
+ * 上传文件
+ *
+ * @param bucketName bucket名称
+ * @param objectName 文件名称
+ * @param stream 文件流
+ * @param size 大小
+ * @param contextType 类型
+ * @throws Exception
+ * @see AWS
+ * API Documentation
+ */
+ public PutObjectResult putObject(String bucketName, String objectName, InputStream stream, long size,
+ String contextType) throws Exception {
+ // String fileName = getFileName(objectName);
+ byte[] bytes = IOUtils.toByteArray(stream);
+ ObjectMetadata objectMetadata = new ObjectMetadata();
+ objectMetadata.setContentLength(size);
+ objectMetadata.setContentType(contextType);
+ ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
+ // 上传
+ return amazonS3.putObject(bucketName, objectName, byteArrayInputStream, objectMetadata);
- }
+ }
- /**
- * 获取文件信息
- * @param bucketName bucket名称
- * @param objectName 文件名称
- * @see AWS
- * API Documentation
- */
- public S3Object getObjectInfo(String bucketName, String objectName) throws Exception {
- @Cleanup
- S3Object object = amazonS3.getObject(bucketName, objectName);
- return object;
- }
+ /**
+ * 获取文件信息
+ *
+ * @param bucketName bucket名称
+ * @param objectName 文件名称
+ * @see AWS
+ * API Documentation
+ */
+ public S3Object getObjectInfo(String bucketName, String objectName) throws Exception {
+ @Cleanup
+ S3Object object = amazonS3.getObject(bucketName, objectName);
+ return object;
+ }
- /**
- * 删除文件
- * @param bucketName bucket名称
- * @param objectName 文件名称
- * @throws Exception
- * @see AWS API
- * Documentation
- */
- public void removeObject(String bucketName, String objectName) throws Exception {
- amazonS3.deleteObject(bucketName, objectName);
- }
+ /**
+ * 删除文件
+ *
+ * @param bucketName bucket名称
+ * @param objectName 文件名称
+ * @throws Exception
+ * @see AWS API
+ * Documentation
+ */
+ public void removeObject(String bucketName, String objectName) throws Exception {
+ amazonS3.deleteObject(bucketName, objectName);
+ }
- @Override
- public void afterPropertiesSet() {
- ClientConfiguration clientConfiguration = new ClientConfiguration();
- clientConfiguration.setMaxConnections(properties.getOss().getMaxConnections());
+ @Override
+ public void afterPropertiesSet() {
+ ClientConfiguration clientConfiguration = new ClientConfiguration();
+ clientConfiguration.setMaxConnections(properties.getOss().getMaxConnections());
- AwsClientBuilder.EndpointConfiguration endpointConfiguration = new AwsClientBuilder.EndpointConfiguration(
- properties.getOss().getEndpoint(), properties.getOss().getRegion());
- AWSCredentials awsCredentials = new BasicAWSCredentials(properties.getOss().getAccessKey(),
- properties.getOss().getSecretKey());
- AWSCredentialsProvider awsCredentialsProvider = new AWSStaticCredentialsProvider(awsCredentials);
- this.amazonS3 = AmazonS3Client.builder()
- .withEndpointConfiguration(endpointConfiguration)
- .withClientConfiguration(clientConfiguration)
- .withCredentials(awsCredentialsProvider)
- .disableChunkedEncoding()
- .withPathStyleAccessEnabled(properties.getOss().getPathStyleAccess())
- .build();
- }
+ AwsClientBuilder.EndpointConfiguration endpointConfiguration = new AwsClientBuilder.EndpointConfiguration(
+ properties.getOss().getEndpoint(), properties.getOss().getRegion());
+ AWSCredentials awsCredentials = new BasicAWSCredentials(properties.getOss().getAccessKey(),
+ properties.getOss().getSecretKey());
+ AWSCredentialsProvider awsCredentialsProvider = new AWSStaticCredentialsProvider(awsCredentials);
+ this.amazonS3 = AmazonS3Client.builder().withEndpointConfiguration(endpointConfiguration)
+ .withClientConfiguration(clientConfiguration).withCredentials(awsCredentialsProvider)
+ .disableChunkedEncoding().withPathStyleAccessEnabled(properties.getOss().getPathStyleAccess()).build();
+ }
}