From 907439044a8d5fad2b768f9000039ef94f12107d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E5=BF=A0=E6=9E=97?= <170083662@qq.com> Date: Thu, 6 Aug 2026 09:15:25 +0800 Subject: [PATCH] =?UTF-8?q?fix(storage):=20=E6=94=AF=E6=8C=81=20MinIO=20?= =?UTF-8?q?=E5=85=BC=E5=AE=B9=20S3=20=E5=8D=8F=E8=AE=AE=E7=9A=84=E4=B8=8A?= =?UTF-8?q?=E4=BC=A0=E6=96=B9=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在 AliOssController 和 FileRecordServiceImpl 中新增 uploadMethod 配置读取 - 针对 uploadMethod 为 minio 时,配置 ClientBuilderConfiguration 使用 V4 签名并自动启用 path-style 访问 - 修改 OSSClient 实例化逻辑,支持带配置参数构建以兼容 MinIO - 图片和视频缩略图及预览图生成逻辑适配 MinIO,不使用阿里云特有的 x-oss-process 参数 - 保证 MinIO 返回的资源 URL 为原始路径,避免图片处理参数导致异常 --- .../system/controller/AliOssController.java | 40 +++++++++++++++---- .../service/impl/FileRecordServiceImpl.java | 16 +++++++- 2 files changed, 48 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/gxwebsoft/common/system/controller/AliOssController.java b/src/main/java/com/gxwebsoft/common/system/controller/AliOssController.java index 0f624bf..825d347 100644 --- a/src/main/java/com/gxwebsoft/common/system/controller/AliOssController.java +++ b/src/main/java/com/gxwebsoft/common/system/controller/AliOssController.java @@ -7,6 +7,8 @@ import com.aliyun.oss.ClientException; import com.aliyun.oss.OSS; import com.aliyun.oss.OSSClientBuilder; import com.aliyun.oss.OSSException; +import com.aliyun.oss.ClientBuilderConfiguration; +import com.aliyun.oss.common.comm.SignVersion; import com.aliyun.oss.common.auth.CredentialsProvider; import com.aliyun.oss.common.auth.DefaultCredentialProvider; import com.aliyun.oss.common.utils.BinaryUtil; @@ -96,6 +98,7 @@ public class AliOssController extends BaseController { String bucketName = settingInfo.getString("bucketName"); String accessKeyId = settingInfo.getString("accessKeyId"); String accessKeySecret = settingInfo.getString("accessKeySecret"); + String uploadMethod = settingInfo.getString("uploadMethod"); // 判断是否登录 String authorization = getAuthorization(); @@ -114,7 +117,18 @@ public class AliOssController extends BaseController { FileRecord result; CredentialsProvider credentialsProvider = new DefaultCredentialProvider(accessKeyId, accessKeySecret); // 创建OSSClient实例。 - OSS ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider); + // MinIO 兼容 S3 协议,需开启 PathStyle 访问(endpoint/bucket/key)并使用 V4 签名 + OSS ossClient; + if ("minio".equals(uploadMethod)) { + ClientBuilderConfiguration minioConfig = new ClientBuilderConfiguration(); + // 3.17 已移除 setPathStyleAccess;用 setExtractSettingFromEndpoint 让 SDK 对 MinIO 这类 + // 非阿里云 endpoint 自动按 path-style 访问,并从 endpoint 推导 region + minioConfig.setSignatureVersion(SignVersion.V4); + minioConfig.setExtractSettingFromEndpoint(true); + ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider, minioConfig); + } else { + ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider); + } try { @@ -162,14 +176,26 @@ public class AliOssController extends BaseController { result.setContentType(contentType); // 根据文件类型设置缩略图和预览图 + // MinIO 不支持阿里云 x-oss-process 图片处理参数,统一返回原图 URL + boolean isMinio = "minio".equals(uploadMethod); if (FileServerUtil.isImage(contentType)) { - // 图片:生成缩略图和压缩预览图 - result.setThumbnail(bucketDomain + path + "?x-oss-process=image/resize,m_fixed,w_100,h_100/quality,Q_90"); - result.setUrl(bucketDomain + path + "?x-oss-process=image/resize,w_750/quality,Q_90"); + if (isMinio) { + result.setThumbnail(bucketDomain + path); + result.setUrl(bucketDomain + path); + } else { + // 图片:生成缩略图和压缩预览图 + result.setThumbnail(bucketDomain + path + "?x-oss-process=image/resize,m_fixed,w_100,h_100/quality,Q_90"); + result.setUrl(bucketDomain + path + "?x-oss-process=image/resize,w_750/quality,Q_90"); + } } else if (contentType != null && contentType.startsWith("video/")) { - // 视频:使用OSS视频截帧生成缩略图(取首帧) - result.setThumbnail(bucketDomain + path + "?x-oss-process=video/snapshot,t_0,f_jpg,w_100,h_100,m_fast"); - result.setUrl(bucketDomain + path); + if (isMinio) { + result.setThumbnail(bucketDomain + path); + result.setUrl(bucketDomain + path); + } else { + // 视频:使用OSS视频截帧生成缩略图(取首帧) + result.setThumbnail(bucketDomain + path + "?x-oss-process=video/snapshot,t_0,f_jpg,w_100,h_100,m_fast"); + result.setUrl(bucketDomain + path); + } } else { // 非图片/视频:直接使用原始URL result.setThumbnail(bucketDomain + path); diff --git a/src/main/java/com/gxwebsoft/common/system/service/impl/FileRecordServiceImpl.java b/src/main/java/com/gxwebsoft/common/system/service/impl/FileRecordServiceImpl.java index 39a6808..d96ca7f 100644 --- a/src/main/java/com/gxwebsoft/common/system/service/impl/FileRecordServiceImpl.java +++ b/src/main/java/com/gxwebsoft/common/system/service/impl/FileRecordServiceImpl.java @@ -6,6 +6,8 @@ import com.aliyun.oss.ClientException; import com.aliyun.oss.OSS; import com.aliyun.oss.OSSClientBuilder; import com.aliyun.oss.OSSException; +import com.aliyun.oss.ClientBuilderConfiguration; +import com.aliyun.oss.common.comm.SignVersion; import com.aliyun.oss.common.auth.CredentialsProvider; import com.aliyun.oss.common.auth.DefaultCredentialProvider; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; @@ -93,8 +95,20 @@ public class FileRecordServiceImpl extends ServiceImpl