fix(storage): 支持 MinIO 兼容 S3 协议的上传方式

- 在 AliOssController 和 FileRecordServiceImpl 中新增 uploadMethod 配置读取
- 针对 uploadMethod 为 minio 时,配置 ClientBuilderConfiguration 使用 V4 签名并自动启用 path-style 访问
- 修改 OSSClient 实例化逻辑,支持带配置参数构建以兼容 MinIO
- 图片和视频缩略图及预览图生成逻辑适配 MinIO,不使用阿里云特有的 x-oss-process 参数
- 保证 MinIO 返回的资源 URL 为原始路径,避免图片处理参数导致异常
This commit is contained in:
2026-08-06 09:15:25 +08:00
parent 39d3c4c894
commit 907439044a
2 changed files with 48 additions and 8 deletions

View File

@@ -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)) {
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/")) {
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);

View File

@@ -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<FileRecordMapper, FileRec
String bucketName = uploadConfig.getString("bucketName");
String accessKeyId = uploadConfig.getString("accessKeyId");
String accessKeySecret = uploadConfig.getString("accessKeySecret");
String uploadMethod = uploadConfig.getString("uploadMethod");
CredentialsProvider credentialsProvider = new DefaultCredentialProvider(accessKeyId, accessKeySecret);
OSS ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider);
// MinIO 兼容 S3 协议,需开启 PathStyle 访问 + 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);
}
for (FileRecord fileRecord : fileRecords) {
fileRecord.setPath(StrUtil.replace(fileRecord.getPath(), bucketDomain.concat("/"), ""));
try {