diff --git a/pom.xml b/pom.xml index 77b3ea5..220a8ff 100644 --- a/pom.xml +++ b/pom.xml @@ -26,7 +26,31 @@ UTF-8 + + + + + com.squareup.okhttp3 + okhttp + 4.12.0 + + + com.squareup.okio + okio + 3.6.0 + + + + + + + com.squareup.okhttp3 + okhttp + 4.12.0 + + org.springframework.boot @@ -297,6 +321,14 @@ 3.17.4 + + + io.minio + minio + 8.5.7 + + com.aliyun 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 3611f9e..a3b016b 100644 --- a/src/main/java/com/gxwebsoft/common/system/controller/AliOssController.java +++ b/src/main/java/com/gxwebsoft/common/system/controller/AliOssController.java @@ -37,6 +37,8 @@ import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.Operation; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; +import io.minio.MinioClient; +import io.minio.UploadObjectArgs; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; @@ -115,26 +117,18 @@ public class AliOssController extends BaseController { // 上传文件结果 FileRecord result; - CredentialsProvider credentialsProvider = new DefaultCredentialProvider(accessKeyId, accessKeySecret); - // 创建OSSClient实例。 - // MinIO 兼容 S3 协议,需开启 PathStyle 访问(endpoint/bucket/key)并使用 V4 签名 - OSS ossClient; - if ("minio".equals(uploadMethod)) { - ClientBuilderConfiguration minioConfig = new ClientBuilderConfiguration(); - // MinIO 兼容 S3:V4 签名 + path-style。自定义域名无法从 endpoint 推导 region, - // 必须显式指定(MinIO 默认 us-east-1),否则 OSSV4Signer.getRegion() 为 null 触发 NPE。 - minioConfig.setSignatureVersion(SignVersion.V4); - minioConfig.setExtractSettingFromEndpoint(true); - // 关闭 CNAME:默认 true 会让 SDK 把自定义域名当 CNAME,走 bucket.endpoint 虚拟主机风格, - // 触发 *.minio-api.websoft.top 证书不匹配。关闭后强制 path-style(endpoint/bucket/key)。 - minioConfig.setSupportCname(false); - ossClient = OSSClientBuilder.create() + boolean isMinio = "minio".equals(uploadMethod); + // MinIO 用官方 minio-java SDK(原生 AWS4-HMAC-SHA256 + path-style); + // aliyun OSS SDK 无 AWS4 签名器,对接不了 MinIO,因此 minio 分支独立使用 MinioClient。 + OSS ossClient = null; + MinioClient minioClient = null; + if (isMinio) { + minioClient = MinioClient.builder() .endpoint(endpoint) - .credentialsProvider(credentialsProvider) - .clientConfiguration(minioConfig) - .region("us-east-1") + .credentials(accessKeyId, accessKeySecret) .build(); } else { + CredentialsProvider credentialsProvider = new DefaultCredentialProvider(accessKeyId, accessKeySecret); ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider); } @@ -145,16 +139,18 @@ public class AliOssController extends BaseController { String path = upload.getAbsolutePath().replace("\\", "/").substring(dir.length()); String originalName = file.getOriginalFilename(); - // 创建PutObjectRequest对象。 - PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, path, upload); - // 如果需要上传时设置存储类型和访问权限,请参考以下示例代码。 - // ObjectMetadata metadata = new ObjectMetadata(); - // metadata.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard.toString()); - // metadata.setObjectAcl(CannedAccessControlList.Private); - // putObjectRequest.setMetadata(metadata); - - // 上传文件。 - PutObjectResult ossResult = ossClient.putObject(putObjectRequest); + // 上传文件到对象存储。 + if (isMinio) { + // minio-java:path 此时无前导 "/",作为对象名(如 2026/08/07/xxx.png),默认 region=us-east-1 + minioClient.uploadObject(UploadObjectArgs.builder() + .bucket(bucketName) + .object(path) + .filename(upload.getAbsolutePath()) + .build()); + } else { + PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, path, upload); + ossClient.putObject(putObjectRequest); + } // 保存记录并返回 result = new FileRecord(); @@ -185,7 +181,7 @@ public class AliOssController extends BaseController { // 根据文件类型设置缩略图和预览图 // MinIO 不支持阿里云 x-oss-process 图片处理参数,统一返回原图 URL - boolean isMinio = "minio".equals(uploadMethod); + isMinio = "minio".equals(uploadMethod); if (FileServerUtil.isImage(contentType)) { if (isMinio) { result.setThumbnail(bucketDomain + path); @@ -236,10 +232,15 @@ public class AliOssController extends BaseController { + "a serious internal problem while trying to communicate with OSS, " + "such as not being able to access the network."); System.out.println("Error Message:" + ce.getMessage()); + } catch (Exception e) { + // 兼容 minio-java 抛出的异常(MinioException / IOException 等) + System.out.println("Caught an upload Exception: " + e.getMessage()); + e.printStackTrace(); } finally { if (ossClient != null) { ossClient.shutdown(); } + // MinioClient 内部复用 HttpClient 连接池,无需显式关闭 } return fail("上传失败", null); } 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 2ed5bfb..2f64f73 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 @@ -22,6 +22,8 @@ import com.gxwebsoft.common.system.param.FileRecordParam; import com.gxwebsoft.common.system.service.CompanyService; import com.gxwebsoft.common.system.service.FileRecordService; import com.gxwebsoft.common.system.service.SettingService; +import io.minio.MinioClient; +import io.minio.RemoveObjectArgs; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; @@ -96,32 +98,31 @@ public class FileRecordServiceImpl extends ServiceImpl 0) { Company company = companyService.getById(fileRecord.getCompanyId());