diff --git a/kernel-d-file/file-sdk-minio/pom.xml b/kernel-d-file/file-sdk-minio/pom.xml
index 0538ec58f..84770658e 100644
--- a/kernel-d-file/file-sdk-minio/pom.xml
+++ b/kernel-d-file/file-sdk-minio/pom.xml
@@ -33,10 +33,6 @@
-
- com.amazonaws
- aws-java-sdk-s3
-
io.minio
minio
diff --git a/kernel-d-file/file-sdk-minio/src/main/java/cn/stylefeng/roses/kernel/file/minio/MinIoFileOperator.java b/kernel-d-file/file-sdk-minio/src/main/java/cn/stylefeng/roses/kernel/file/minio/MinIoFileOperator.java
index 762dcdd77..931d2ee91 100644
--- a/kernel-d-file/file-sdk-minio/src/main/java/cn/stylefeng/roses/kernel/file/minio/MinIoFileOperator.java
+++ b/kernel-d-file/file-sdk-minio/src/main/java/cn/stylefeng/roses/kernel/file/minio/MinIoFileOperator.java
@@ -36,14 +36,14 @@ import cn.stylefeng.roses.kernel.file.api.exception.FileException;
import cn.stylefeng.roses.kernel.file.api.exception.enums.FileExceptionEnum;
import cn.stylefeng.roses.kernel.file.api.expander.FileConfigExpander;
import cn.stylefeng.roses.kernel.file.api.pojo.props.MinIoProperties;
+import cn.stylefeng.roses.kernel.file.minio.factory.MinIoConfigFactory;
import cn.stylefeng.roses.kernel.rule.util.HttpServletUtil;
-import io.minio.MinioClient;
-import io.minio.errors.InvalidEndpointException;
-import io.minio.errors.InvalidPortException;
-import io.minio.policy.PolicyType;
+import io.minio.*;
+import lombok.extern.slf4j.Slf4j;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
+import java.rmi.NoSuchObjectException;
import java.util.HashMap;
import java.util.Map;
@@ -53,6 +53,7 @@ import java.util.Map;
* @author fengshuonan
* @since 2020/10/31 10:35
*/
+@Slf4j
public class MinIoFileOperator implements FileOperatorApi {
private final Object LOCK = new Object();
@@ -84,12 +85,7 @@ public class MinIoFileOperator implements FileOperatorApi {
String secretKey = minIoProperties.getSecretKey();
// 创建minioClient实例
- try {
- minioClient = new MinioClient(endpoint, accessKey, secretKey);
- } catch (InvalidEndpointException | InvalidPortException e) {
- // 组装提示信息
- throw new FileException(FileExceptionEnum.MINIO_FILE_ERROR, e.getMessage());
- }
+ minioClient = MinioClient.builder().endpoint(endpoint).credentials(accessKey, secretKey).build();
}
@Override
@@ -105,52 +101,85 @@ public class MinIoFileOperator implements FileOperatorApi {
@Override
public boolean doesBucketExist(String bucketName) {
try {
- return minioClient.bucketExists(bucketName);
+ return minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
} catch (Exception e) {
- // 组装提示信息
- throw new FileException(FileExceptionEnum.MINIO_FILE_ERROR, e.getMessage());
+ log.error("MinIo校验桶是否存在时异常:", e);
+ return false;
}
}
@Override
public void setBucketAcl(String bucketName, BucketAuthEnum bucketAuthEnum) {
- setFileAcl(bucketName, "*", bucketAuthEnum);
+ try {
+ // 创建规则的json
+ String policyJson = MinIoConfigFactory.createPolicyJson(bucketAuthEnum, bucketName);
+
+ // 使用 SetBucketPolicyArgs 设置策略
+ SetBucketPolicyArgs args = SetBucketPolicyArgs.builder()
+ .bucket(bucketName)
+ .config(policyJson)
+ .build();
+ minioClient.setBucketPolicy(args);
+ } catch (Exception e) {
+ log.error("Error occurred while setting bucket ACL: ", e);
+ throw new FileException(FileExceptionEnum.MINIO_FILE_ERROR, e.getMessage());
+ }
}
@Override
public boolean isExistingFile(String bucketName, String key) {
- InputStream inputStream = null;
try {
- inputStream = minioClient.getObject(bucketName, key);
- if (inputStream != null) {
- return true;
- }
- } catch (Exception e) {
+ // 使用 StatObjectArgs 构建查询参数
+ StatObjectResponse response = minioClient.statObject(
+ StatObjectArgs.builder()
+ .bucket(bucketName)
+ .object(key)
+ .build()
+ );
+ // 如果文件存在,statObject 不会抛出异常,返回 true
+ return true;
+ } catch (NoSuchObjectException e) {
+ // 如果文件不存在,会抛出 NoSuchObjectException,返回 false
+ return false;
+ } catch (Exception e) {
+ log.error("MINIO无法找到文件! ", e);
return false;
- } finally {
- IoUtil.close(inputStream);
}
- return false;
}
@Override
public void storageFile(String bucketName, String key, byte[] bytes) {
- if (bytes != null && bytes.length > 0) {
- // 字节数组转字节数组输入流
+ if (bytes == null || bytes.length == 0) {
+ return;
+ }
+
+ try {
+ // 检查存储桶是否存在,不存在直接返回
+ boolean isBucketExist = this.doesBucketExist(bucketName);
+ if (!isBucketExist) {
+ log.error("无法存储文件到桶,桶不存在!桶名称:{}", bucketName);
+ return;
+ }
+
+ // 将字节数组转换为输入流
ByteArrayInputStream byteArrayInputStream = IoUtil.toStream(bytes);
- // 获取文件类型
- ByteArrayInputStream tmp = IoUtil.toStream(bytes);
- String type = FileTypeUtil.getType(tmp);
+ String type = FileTypeUtil.getType(byteArrayInputStream);
String fileContentType = getFileContentType(String.format("%s%s", ".", type));
- try {
- minioClient.putObject(bucketName, key, byteArrayInputStream, bytes.length, fileContentType);
- } catch (Exception e) {
-
- // 组装提示信息
- throw new FileException(FileExceptionEnum.MINIO_FILE_ERROR, e.getMessage());
- }
+ // 上传文件
+ minioClient.putObject(
+ PutObjectArgs.builder()
+ .bucket(bucketName)
+ .object(key)
+ // -1 表示不限制流的大小
+ .stream(byteArrayInputStream, bytes.length, -1)
+ .contentType(fileContentType)
+ .build()
+ );
+ } catch (Exception e) {
+ log.error("MINIO文件操作异常:", e);
+ throw new FileException(FileExceptionEnum.MINIO_FILE_ERROR, e.getMessage());
}
}
@@ -165,10 +194,10 @@ public class MinIoFileOperator implements FileOperatorApi {
@Override
public byte[] getFileBytes(String bucketName, String key) {
try {
- InputStream inputStream = minioClient.getObject(bucketName, key);
+ InputStream inputStream = minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(key).build());
return IoUtil.readBytes(inputStream);
} catch (Exception e) {
- // 组装提示信息
+ log.error("MINIO文件操作异常:", e);
throw new FileException(FileExceptionEnum.MINIO_FILE_ERROR, e.getMessage());
}
}
@@ -176,18 +205,15 @@ public class MinIoFileOperator implements FileOperatorApi {
@Override
public void setFileAcl(String bucketName, String key, BucketAuthEnum bucketAuthEnum) {
try {
- if (bucketAuthEnum.equals(BucketAuthEnum.PRIVATE)) {
- minioClient.setBucketPolicy(bucketName, key, PolicyType.NONE);
- } else if (bucketAuthEnum.equals(BucketAuthEnum.PUBLIC_READ)) {
- minioClient.setBucketPolicy(bucketName, key, PolicyType.READ_ONLY);
- } else if (bucketAuthEnum.equals(BucketAuthEnum.PUBLIC_READ_WRITE)) {
- minioClient.setBucketPolicy(bucketName, key, PolicyType.READ_WRITE);
- } else if (bucketAuthEnum.equals(BucketAuthEnum.MINIO_WRITE_ONLY)) {
- minioClient.setBucketPolicy(bucketName, key, PolicyType.WRITE_ONLY);
- }
+ // 根据枚举值设置对应的策略
+ String policyJson = MinIoConfigFactory.createKeyPolicyJson(bucketName, key, bucketAuthEnum);
+ SetBucketPolicyArgs args = SetBucketPolicyArgs.builder()
+ .bucket(bucketName)
+ .config(policyJson)
+ .build();
+ minioClient.setBucketPolicy(args);
} catch (Exception e) {
-
- // 组装提示信息
+ log.error("MINIO文件操作异常:", e);
throw new FileException(FileExceptionEnum.MINIO_FILE_ERROR, e.getMessage());
}
}
@@ -195,9 +221,23 @@ public class MinIoFileOperator implements FileOperatorApi {
@Override
public void copyFile(String originBucketName, String originFileKey, String newBucketName, String newFileKey) {
try {
- minioClient.copyObject(originBucketName, originFileKey, newBucketName, newFileKey);
+ // 构建源文件的 CopySource 对象
+ CopySource copySource = CopySource.builder()
+ .bucket(originBucketName)
+ .object(originFileKey)
+ .build();
+
+ // 构建拷贝文件的目标参数
+ CopyObjectArgs copyObjectArgs = CopyObjectArgs.builder()
+ .source(copySource)
+ .bucket(newBucketName)
+ .object(newFileKey)
+ .build();
+
+ // 执行拷贝操作
+ minioClient.copyObject(copyObjectArgs);
} catch (Exception e) {
- // 组装提示信息
+ log.error("MINIO文件操作异常:", e);
throw new FileException(FileExceptionEnum.MINIO_FILE_ERROR, e.getMessage());
}
}
@@ -211,8 +251,12 @@ public class MinIoFileOperator implements FileOperatorApi {
// 获取context-path
String contextPath = HttpServletUtil.getRequest().getContextPath();
- return FileConfigExpander.getServerDeployHost() + contextPath + FileConstants.FILE_PREVIEW_BY_OBJECT_NAME + "?fileBucket=" + bucketName + "&fileObjectName=" + key + "&token=" + token;
-
+ return FileConfigExpander.getServerDeployHost()
+ + contextPath
+ + FileConstants.FILE_PREVIEW_BY_OBJECT_NAME
+ + "?fileBucket=" + bucketName
+ + "&fileObjectName=" + key
+ + "&token=" + token;
}
@Override
@@ -220,18 +264,21 @@ public class MinIoFileOperator implements FileOperatorApi {
// 获取context-path
String contextPath = HttpServletUtil.getRequest().getContextPath();
- return FileConfigExpander.getServerDeployHost() + contextPath + FileConstants.FILE_PREVIEW_BY_OBJECT_NAME + "?fileBucket=" + bucketName + "&fileObjectName=" + key;
+ return FileConfigExpander.getServerDeployHost()
+ + contextPath
+ + FileConstants.FILE_PREVIEW_BY_OBJECT_NAME
+ + "?fileBucket=" + bucketName
+ + "&fileObjectName=" + key;
}
@Override
public void deleteFile(String bucketName, String key) {
try {
- minioClient.removeObject(bucketName, key);
+ minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(key).build());
} catch (Exception e) {
- // 组装提示信息
+ log.error("MINIO文件操作异常:", e);
throw new FileException(FileExceptionEnum.MINIO_FILE_ERROR, e.getMessage());
}
-
}
@Override
@@ -247,7 +294,7 @@ public class MinIoFileOperator implements FileOperatorApi {
*/
private Map getFileContentType() {
synchronized (LOCK) {
- if (contentType.size() == 0) {
+ if (contentType.isEmpty()) {
contentType.put(".bmp", "application/x-bmp");
contentType.put(".gif", "image/gif");
contentType.put(".fax", "image/fax");
diff --git a/kernel-d-file/file-sdk-minio/src/main/java/cn/stylefeng/roses/kernel/file/minio/factory/MinIoConfigFactory.java b/kernel-d-file/file-sdk-minio/src/main/java/cn/stylefeng/roses/kernel/file/minio/factory/MinIoConfigFactory.java
new file mode 100644
index 000000000..7caeb8b4e
--- /dev/null
+++ b/kernel-d-file/file-sdk-minio/src/main/java/cn/stylefeng/roses/kernel/file/minio/factory/MinIoConfigFactory.java
@@ -0,0 +1,157 @@
+package cn.stylefeng.roses.kernel.file.minio.factory;
+
+import cn.stylefeng.roses.kernel.file.api.enums.BucketAuthEnum;
+
+/**
+ * MinIO配置工厂
+ *
+ * @author fengshuonan
+ * @since 2025/4/30 21:56
+ */
+public class MinIoConfigFactory {
+
+ /**
+ * 生成桶的策略JSON
+ *
+ * @author fengshuonan
+ * @since 2025/4/30 21:53
+ */
+ public static String createPolicyJson(BucketAuthEnum bucketAuthEnum, String bucketName) {
+ switch (bucketAuthEnum) {
+ case PRIVATE:
+ return "{\n" +
+ " \"Version\": \"2012-10-17\",\n" +
+ " \"Statement\": [\n" +
+ " {\n" +
+ " \"Effect\": \"Deny\",\n" +
+ " \"Principal\": \"*\",\n" +
+ " \"Action\": \"s3:*\",\n" +
+ " \"Resource\": \"arn:aws:s3:::" + bucketName + "/*\"\n" +
+ " }\n" +
+ " ]\n" +
+ "}";
+ case PUBLIC_READ:
+ return "{\n" +
+ " \"Version\": \"2012-10-17\",\n" +
+ " \"Statement\": [\n" +
+ " {\n" +
+ " \"Effect\": \"Allow\",\n" +
+ " \"Principal\": \"*\",\n" +
+ " \"Action\": \"s3:GetObject\",\n" +
+ " \"Resource\": \"arn:aws:s3:::" + bucketName + "/*\"\n" +
+ " }\n" +
+ " ]\n" +
+ "}";
+ case PUBLIC_READ_WRITE:
+ return "{\n" +
+ " \"Version\": \"2012-10-17\",\n" +
+ " \"Statement\": [\n" +
+ " {\n" +
+ " \"Effect\": \"Allow\",\n" +
+ " \"Principal\": \"*\",\n" +
+ " \"Action\": [\n" +
+ " \"s3:GetObject\",\n" +
+ " \"s3:PutObject\"\n" +
+ " ],\n" +
+ " \"Resource\": \"arn:aws:s3:::" + bucketName + "/*\"\n" +
+ " }\n" +
+ " ]\n" +
+ "}";
+ case MINIO_WRITE_ONLY:
+ return "{\n" +
+ " \"Version\": \"2012-10-17\",\n" +
+ " \"Statement\": [\n" +
+ " {\n" +
+ " \"Effect\": \"Allow\",\n" +
+ " \"Principal\": \"*\",\n" +
+ " \"Action\": \"s3:PutObject\",\n" +
+ " \"Resource\": \"arn:aws:s3:::" + bucketName + "/*\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"Effect\": \"Deny\",\n" +
+ " \"Principal\": \"*\",\n" +
+ " \"Action\": \"s3:GetObject\",\n" +
+ " \"Resource\": \"arn:aws:s3:::" + bucketName + "/*\"\n" +
+ " }\n" +
+ " ]\n" +
+ "}";
+ default:
+ throw new IllegalArgumentException("Unsupported bucket auth enum: " + bucketAuthEnum);
+ }
+ }
+
+ /**
+ * 生成文件的策略JSON
+ *
+ * @author fengshuonan
+ * @since 2025/4/30 22:15
+ */
+ public static String createKeyPolicyJson(String bucketName, String key, BucketAuthEnum bucketAuthEnum) {
+ switch (bucketAuthEnum) {
+ case PRIVATE:
+ return String.format(
+ "{\n" +
+ " \"Version\": \"2012-10-17\",\n" +
+ " \"Statement\": [\n" +
+ " {\n" +
+ " \"Effect\": \"Deny\",\n" +
+ " \"Principal\": \"*\",\n" +
+ " \"Action\": \"s3:*\",\n" +
+ " \"Resource\": \"arn:aws:s3:::%s/%s\"\n" +
+ " }\n" +
+ " ]\n" +
+ "}", bucketName, key);
+ case PUBLIC_READ:
+ return String.format(
+ "{\n" +
+ " \"Version\": \"2012-10-17\",\n" +
+ " \"Statement\": [\n" +
+ " {\n" +
+ " \"Effect\": \"Allow\",\n" +
+ " \"Principal\": \"*\",\n" +
+ " \"Action\": \"s3:GetObject\",\n" +
+ " \"Resource\": \"arn:aws:s3:::%s/%s\"\n" +
+ " }\n" +
+ " ]\n" +
+ "}", bucketName, key);
+ case PUBLIC_READ_WRITE:
+ return String.format(
+ "{\n" +
+ " \"Version\": \"2012-10-17\",\n" +
+ " \"Statement\": [\n" +
+ " {\n" +
+ " \"Effect\": \"Allow\",\n" +
+ " \"Principal\": \"*\",\n" +
+ " \"Action\": [\n" +
+ " \"s3:GetObject\",\n" +
+ " \"s3:PutObject\"\n" +
+ " ],\n" +
+ " \"Resource\": \"arn:aws:s3:::%s/%s\"\n" +
+ " }\n" +
+ " ]\n" +
+ "}", bucketName, key);
+ case MINIO_WRITE_ONLY:
+ return String.format(
+ "{\n" +
+ " \"Version\": \"2012-10-17\",\n" +
+ " \"Statement\": [\n" +
+ " {\n" +
+ " \"Effect\": \"Allow\",\n" +
+ " \"Principal\": \"*\",\n" +
+ " \"Action\": \"s3:PutObject\",\n" +
+ " \"Resource\": \"arn:aws:s3:::%s/%s\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"Effect\": \"Deny\",\n" +
+ " \"Principal\": \"*\",\n" +
+ " \"Action\": \"s3:GetObject\",\n" +
+ " \"Resource\": \"arn:aws:s3:::%s/%s\"\n" +
+ " }\n" +
+ " ]\n" +
+ "}", bucketName, key);
+ default:
+ throw new IllegalArgumentException("Unsupported bucket auth enum: " + bucketAuthEnum);
+ }
+ }
+
+}
diff --git a/pom.xml b/pom.xml
index f5cc62f54..681e06763 100644
--- a/pom.xml
+++ b/pom.xml
@@ -129,8 +129,7 @@
2.5.1
3.1.57
7.9.2
- 1.11.106
- 3.0.10
+ 8.5.17
4.5.2
1.6.2
3.0.22
@@ -253,13 +252,6 @@
-
- com.amazonaws
- aws-java-sdk-bom
- ${aws.sdk.version}
- pom
- import
-
io.minio
minio