mirror of https://gitee.com/stylefeng/roses
【8.3.4】【file】更新新版MinIO客户端的操作
parent
9fc535b87b
commit
86da86232b
|
@ -33,10 +33,6 @@
|
|||
</dependency>
|
||||
|
||||
<!--minio客户端-->
|
||||
<dependency>
|
||||
<groupId>com.amazonaws</groupId>
|
||||
<artifactId>aws-java-sdk-s3</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.minio</groupId>
|
||||
<artifactId>minio</artifactId>
|
||||
|
|
|
@ -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<String, String> 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");
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
10
pom.xml
10
pom.xml
|
@ -129,8 +129,7 @@
|
|||
<qingyun.oss.version>2.5.1</qingyun.oss.version>
|
||||
<qcloud.sms>3.1.57</qcloud.sms>
|
||||
<elasticsearch.version>7.9.2</elasticsearch.version>
|
||||
<aws.sdk.version>1.11.106</aws.sdk.version>
|
||||
<minio.version>3.0.10</minio.version>
|
||||
<minio.version>8.5.17</minio.version>
|
||||
<rocketmq.version>4.5.2</rocketmq.version>
|
||||
<easy.captcha>1.6.2</easy.captcha>
|
||||
<guns.groovy.version>3.0.22</guns.groovy.version>
|
||||
|
@ -253,13 +252,6 @@
|
|||
</dependency>
|
||||
|
||||
<!--MinIo客户端sdk-->
|
||||
<dependency>
|
||||
<groupId>com.amazonaws</groupId>
|
||||
<artifactId>aws-java-sdk-bom</artifactId>
|
||||
<version>${aws.sdk.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.minio</groupId>
|
||||
<artifactId>minio</artifactId>
|
||||
|
|
Loading…
Reference in New Issue