注:本文除代码外多数为AI生成
最近因为有项目需要换成Amazon S3的云存储,所以把之前做过的minio部分做一个记录,后面也会把基于这版改造的S3方法发出来记录。
MinIO是一款高性能、分布式对象存储服务器,设计用于在大规模环境中存储和检索非结构化数据集,如图像、视频和日志文件。它完全开源,遵循Apache License v2.0,并且与Amazon S3 API兼容,这使得从现有的S3环境迁移变得简单。MinIO支持多租户,确保了数据的安全性和隔离性,同时提供了多种数据持久性和一致性保障机制。由于其出色的性能特性,如高吞吐量和低延迟,MinIO成为了众多企业和组织在构建现代云基础设施时的首选对象存储解决方案。
hosts
文件或DNS服务来解决集群内部的域名或IP地址,避免直接在配置文件中硬编码IP地址,这有助于在节点变化时更容易地维护集群。export MINIO_ACCESS_KEY=admin
export MINIO_SECRET_KEY=minioadmin
#console-address参数可设可不设
./minio server --address ":9001" --console-address ":9011"
"http://ipA:9001/arcfile/minioData/data"
"http://ipB:9001/arcfile/minioData/data"
"http://ipC:9001/arcfile/minioData/data"
"http://ipD:9001/arcfile/minioData/data" >/arcfile/minioData/logs/start.txt 2>&1 &
RUNNING_USER=root
MINIO_HOME=/opt/minio
MINIO_HOST=192.168.222.10
#accesskey and secretkey
ACCESS_KEY=admin
SECRET_KEY=minioadmin
for i in {01..04}; do
START_CMD="MINIO_ACCESS_KEY=${ACCESS_KEY} MINIO_SECRET_KEY=${SECRET_KEY} nohup ${MINIO_HOME}/minio server --address "${MINIO_HOST}:90${i}" http://${MINIO_HOST}:9001/opt/min-data1 http://${MINIO_HOST}:9002/opt/min-data2 http://${MINIO_HOST}:9003/opt/min-data3 http://${MINIO_HOST}:9004/opt/min-data4 > ${MINIO_HOME}/minio-90${i}.log 2>&1 &"
su - ${RUNNING_USER} -c "${START_CMD}"
done
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.3.3</version>
</dependency>
<!--如果出现okhttp依赖冲突,添加下面依赖-->
<!-- <dependency>-->
<!-- <groupId>com.squareup.okhttp3</groupId>-->
<!-- <artifactId>okhttp</artifactId>-->
<!-- <version>4.9.0</version>-->
<!-- </dependency>-->
import io.minio.MinioClient;
import io.minio.errors.*;
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.logging.Logger;
@Configuration
public class MinioClientConfig {
private final Logger log = Logger.getLogger(this.getClass().getName());
@Value("${config.minio.url}")
private String MINIO_URL;
@Value("${config.minio.accessKey}")
private String MINIO_ACCESS_KEY;
@Value("${config.minio.secretKey}")
private String MINIO_SECRET_KEY;
@Bean
public MinioClient getMinioClient() {
if (MINIO_URL.length() == 0 || MINIO_URL == null) {
throw new IllegalArgumentException("\n请正确配置Minio服务器的 URL 连接参数");
}
if (MINIO_ACCESS_KEY.length() == 0 || MINIO_ACCESS_KEY == null) {
throw new IllegalArgumentException("\n请正确配置Minio服务器的 ACCESS_KEY 连接参数");
}
if (MINIO_SECRET_KEY.length() == 0 || MINIO_SECRET_KEY == null) {
throw new IllegalArgumentException("\n请正确配置Minio服务器的 SECRET_KEY 连接参数");
}
MinioClient minioClient = MinioClient.builder()
.endpoint(MINIO_URL)
.credentials(MINIO_ACCESS_KEY, MINIO_SECRET_KEY)
.build();
try {
minioClient.listBuckets();
} catch (ErrorResponseException e) {
e.printStackTrace();
throw new RuntimeException("\nMinio服务器连接异常\n请检查所配置的Minio连接信息Access-key和Secret-Key是否正确");
} catch (InsufficientDataException e) {
e.printStackTrace();
} catch (InternalException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (InvalidResponseException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException("\nMinio服务器连接异常\n请检查Minio服务器是否已开启或所配置的Minio_url连接信息是否正确");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (ServerException e) {
e.printStackTrace();
} catch (XmlParserException e) {
e.printStackTrace();
}
log.info("Minio服务器连接成功,URL = " + MINIO_URL);
return minioClient;
}
}
public boolean createBucket(String bucketName) throws RuntimeException {
minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
}
public void BucketAccessPublic(String bucketName) {
String config = "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Action\":[\"s3:ListBucketMultipartUploads\",\"s3:GetBucketLocation\",\"s3:ListBucket\"],\"Resource\":[\"arn:aws:s3:::" + bucketName + "\"]},{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Action\":[\"s3:ListMultipartUploadParts\",\"s3:PutObject\",\"s3:AbortMultipartUpload\",\"s3:DeleteObject\",\"s3:GetObject\"],\"Resource\":[\"arn:aws:s3:::" + bucketName + "/*\"]}]}";
minioClient.setBucketPolicy(SetBucketPolicyArgs.builder().bucket(bucketName).config(config).build();
}
uploadObject()
//上传本地文件
public boolean uploadObject(String bucketName, String targetObject, String sourcePath) {
try {
minioClient.uploadObject(UploadObjectArgs.builder()
.bucket(bucketName)
.object(targetObject)
.filename(sourcePath)
.build());
} catch (ErrorResponseException e) {
e.printStackTrace();
return false;
} catch (InsufficientDataException e) {
e.printStackTrace();
} catch (InternalException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (InvalidResponseException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (ServerException e) {
e.printStackTrace();
} catch (XmlParserException e) {
e.printStackTrace();
}
return true;
}
putObject()
public boolean putObject(String bucketName, String object, InputStream inputStream) {
try {
minioClient.putObject(PutObjectArgs.builder()
.bucket(bucketName)
.object(object)
//.contentType("application/pdf")不设置的话默认是"application/stream",这就是为什么某些文件上传上去无法直接预览的问题
.stream(inputStream, -1, 10485760)
//.tags(tags)上传可以直接携带标签
.build());
} catch (ErrorResponseException e) {
e.printStackTrace();
return false;
} catch (InsufficientDataException e) {
e.printStackTrace();
} catch (InternalException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (InvalidResponseException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (ServerException e) {
e.printStackTrace();
} catch (XmlParserException e) {
e.printStackTrace();
}
return true;
}
public GetObjectResponse getObject(String bucketName, String object) {
GetObjectResponse object1 = null;//这个对象是集成了InputStream的FilterInputStream类,所以是可以直接用流来处理文件的
try {
object1 = minioClient.getObject(GetObjectArgs.builder()
.bucket(bucketName)
.object(object)
.build());
} catch (ErrorResponseException e) {
e.printStackTrace();
} catch (InsufficientDataException e) {
e.printStackTrace();
} catch (InternalException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (InvalidResponseException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (ServerException e) {
e.printStackTrace();
} catch (XmlParserException e) {
e.printStackTrace();
}
return object1;
}
/**
* 生成预签名URL,允许外部在限定时间内访问指定的MinIO对象。
*
* @param bucketName 存储桶名称
* @param object 对象名称
* @param expire 过期时间,单位是分钟
* @param map 用于自定义HTTP响应头的映射,例如设置Content-Type
* @return 返回预签名的URL,可以用于直接访问对象
*/
public String presignedURLofObject(String bucketName, String object, int expire, Map<String, String> map) {
// 设置响应的内容类型为application/json
map.put("response-content-type", "application/json");
// 初始化预签名URL字符串
String presignedObjectUrl = "";
// 尝试获取预签名的URL
try {
// 构建获取预签名URL的参数
presignedObjectUrl = minioClient.getPresignedObjectUrl(
GetPresignedObjectUrlArgs.builder()
.bucket(bucketName) // 设置存储桶名称
.object(object) // 设置对象名称
.method(Method.GET) // 设置HTTP方法为GET
.expiry(expire, TimeUnit.MINUTES) // 设置过期时间为expire分钟后
//.extraQueryParams(map) // 注释掉的代码,用于设置额外的查询参数
.build() // 构建参数对象
);
} catch (ErrorResponseException e) {
// 处理错误响应异常
e.printStackTrace();
} catch (InsufficientDataException e) {
// 数据不足异常
e.printStackTrace();
} catch (InternalException e) {
// MinIO内部异常
e.printStackTrace();
} catch (InvalidKeyException e) {
// 无效的访问密钥异常
e.printStackTrace();
} catch (InvalidResponseException e) {
// 无效的响应异常
e.printStackTrace();
} catch (IOException e) {
// 输入输出异常
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
// 不存在算法异常
e.printStackTrace();
} catch (XmlParserException e) {
// XML解析异常
e.printStackTrace();
} catch (ServerException e) {
// 服务器异常
e.printStackTrace();
}
// 返回预签名的URL
return presignedObjectUrl;
}
MinioService
import io.minio.ComposeSource;
import io.minio.GetObjectResponse;
import io.minio.Result;
import io.minio.StatObjectResponse;
import io.minio.messages.Bucket;
import io.minio.messages.Item;
import org.springframework.stereotype.Service;
import java.io.InputStream;
import java.util.List;
import java.util.Map;
/**
* MinioService接口,定义了与MinIO对象存储系统交互的方法集。
*/
@Service
public interface MinioService {
/**
* 检查指定的存储桶是否存在。
*
* @param bucketName 存储桶名称
* @return 如果存储桶存在则返回true,否则返回false。
*/
boolean ifExistsBucket(String bucketName);
/**
* 创建一个新的存储桶。
*
* @param bucketName 要创建的存储桶名称
* @throws RuntimeException 如果创建失败抛出运行时异常
* @return 如果创建成功则返回true,否则返回false。
*/
boolean createBucket(String bucketName) throws RuntimeException;
/**
* 删除指定的存储桶。
*
* @param bucketName 要删除的存储桶名称
* @return 如果删除成功则返回true,否则返回false。
*/
boolean removeBucket(String bucketName);
/**
* 列出所有已存在的存储桶。
*
* @return 包含所有存储桶信息的列表。
*/
List<Bucket> alreadyExistBuckets();
/**
* 列出指定存储桶中的对象。
*
* @param bucketName 要列出对象的存储桶名称
* @param predir 可选前缀,用于过滤对象名
* @param recursive 是否递归列出子目录的对象
* @return 包含匹配条件的对象列表。
*/
List<Result<Item>> listObjects(String bucketName, String predir, boolean recursive);
/**
* 列出指定存储桶中的对象,用于组成对象操作。
*
* @param bucketName 要列出对象的存储桶名称
* @param predir 可选前缀,用于过滤对象名
* @return 包含对象信息的List<ComposeSource>对象列表。
*/
List<ComposeSource> listObjects(String bucketName, String predir);
/**
* 复制一个对象到另一个位置。
*
* @param pastBucket 原始存储桶名称
* @param pastObject 原始对象名称
* @param newBucket 目标存储桶名称
* @param newObject 目标对象名称
* @return 如果复制成功则返回true,否则返回false。
*/
boolean copyObject(String pastBucket, String pastObject, String newBucket, String newObject);
/**
* 下载存储桶中的对象到本地文件系统。
*
* @param bucketName 存储桶名称
* @param objectName 对象名称
* @param targetPath 目标文件路径
* @return 如果下载成功则返回true,否则返回false。
*/
boolean downObject(String bucketName, String objectName, String targetPath);
/**
* 生成一个预签名的URL,允许外部访问指定的对象。
*
* @param bucketName 存储桶名称
* @param object 对象名称
* @param expire URL的有效期(分钟)
* @return 预签名的URL。
*/
String presignedURLofObject(String bucketName, String object, int expire);
/**
* 生成一个预签名的URL,允许外部访问指定的对象,并自定义HTTP头部。
*
* @param bucketName 存储桶名称
* @param object 对象名称
* @param expire URL的有效期(分钟)
* @param map 自定义的HTTP头部信息
* @return 预签名的URL。
*/
String presignedURLofObject(String bucketName, String object, int expire, Map<String, String> map);
/**
* 删除存储桶中的对象。
*
* @param bucketName 存储桶名称
* @param object 对象名称
* @return 如果删除成功则返回true,否则返回false。
*/
boolean deleteObject(String bucketName, String object);
/**
* 上传本地文件到存储桶。
*
* @param bucketName 存储桶名称
* @param targetObject 目标对象名称
* @param sourcePath 本地文件路径
* @return 如果上传成功则返回true,否则返回false。
*/
boolean uploadObject(String bucketName, String targetObject, String sourcePath);
/**
* 从InputStream上传数据到存储桶。
*
* @param bucketName 存储桶名称
* @param object 对象名称
* @param inputStream 数据流
* @return 如果上传成功则返回true,否则返回false。
*/
boolean putObject(String bucketName, String object, InputStream inputStream);
/**
* 从InputStream上传数据到存储桶,并附带标签。
*
* @param bucketName 存储桶名称
* @param object 对象名称
* @param inputStream 数据流
* @param tags 对象的标签集合
* @return 如果上传成功则返回true,否则返回false。
*/
boolean putObject(String bucketName, String object, InputStream inputStream, Map<String, String> tags);
/**
* 获取存储桶中的对象信息。
*
* @param bucketName 存储桶名称
* @param object 对象名称
* @return 对象的响应信息。
*/
GetObjectResponse getObject(String bucketName, String object);
/**
* 检查存储桶中是否包含指定文件。
*
* @param bucketName 存储桶名称
* @param filename 文件名称
* @param recursive 是否递归查找
* @return 如果文件存在则返回true,否则返回false。
*/
boolean fileifexist(String bucketName, String filename, boolean recursive);
/**
* 获取对象的元数据标签。
*
* @param bucketName 存储桶名称
* @param object 对象名称
* @return 对象的元数据标签集合。
*/
Map<String, String> getTags(String bucketName, String object);
/**
* 添加或更新对象的标签。
*
* @param bucketName 存储桶名称
* @param object 对象名称
* @param addTags 要添加或更新的标签集合
* @return 如果操作成功则返回true,否则返回false。
*/
boolean addTags(String bucketName, String object, Map<String, String> addTags);
/**
* 获取对象的状态信息。
*
* @param bucketName 存储桶名称
* @param object 对象名称
* @return 对象的状态信息。
*/
StatObjectResponse statObject(String bucketName, String object);
/**
* 检查存储桶中对象是否存在。
*
* @param bucketName 存储桶名称
* @param objectName 对象名称
* @return 如果对象存在则返回true,否则返回false。
*/
boolean ifExistObject(String bucketName, String objectName);
/**
* 从其他对象名中提取元名称。
*
* @param objectName 对象名称
* @return 提取的元名称。
*/
String getMetaNameFromOther(String objectName);
/**
* 更改对象的标签。
*
* @param object 对象名称
* @param tag 新的标签值
* @return 如果更改成功则返回true,否则返回false。
*/
boolean changeTag(String object, String tag);
/**
* 设置存储桶的公共访问权限。
*
* @param bucketName 存储桶名称
*/
void BucketAccessPublic(String bucketName);
}
MinioServiceImpl
import com.aspose.cad.internal.Y.S;
import com.xagxsj.erms.model.BucketName;
import com.xagxsj.erms.model.ObjectTags;
import com.xagxsj.erms.service.MinioService;
import com.xagxsj.erms.utils.FileUtil;
import io.minio.*;
import io.minio.errors.*;
import io.minio.http.Method;
import io.minio.messages.Bucket;
import io.minio.messages.Item;
import io.minio.messages.Tags;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
import static com.xagxsj.erms.model.BucketName.METADATA;
@Service
public class MinioServiceImpl implements MinioService {
private final Logger log = Logger.getLogger(this.getClass().getName());
@Qualifier("getMinioClient")
@Autowired
MinioClient minioClient;
/**
* 检查指定的存储桶是否存在于MinIO服务器上。
*
* @param bucketName 要检查的存储桶名称。
* @return 如果存储桶存在,则返回true;否则返回false。
*/
@Override
public boolean ifExistsBucket(String bucketName) {
boolean result = false;
try {
result = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
} catch (ErrorResponseException e) {
e.printStackTrace();
return false;
} catch (InsufficientDataException | InternalException | InvalidKeyException | InvalidResponseException | IOException | NoSuchAlgorithmException | ServerException | XmlParserException e) {
e.printStackTrace();
}
return result;
}
/**
* 在MinIO服务器上创建一个新的存储桶。
*
* @param bucketName 要创建的存储桶名称。
* @throws RuntimeException 如果尝试创建一个已存在的存储桶,则抛出此异常。
* @return 如果存储桶创建成功,则返回true;否则返回false。
*/
@Override
public boolean createBucket(String bucketName) throws RuntimeException {
if (ifExistsBucket(bucketName)) {
throw new RuntimeException("桶已存在");
}
try {
minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
} catch (ErrorResponseException | InsufficientDataException | InternalException | InvalidKeyException | InvalidResponseException | IOException | NoSuchAlgorithmException | ServerException | XmlParserException e) {
e.printStackTrace();
}
return ifExistsBucket(bucketName);
}
/**
* 从MinIO服务器上删除一个存储桶。
*
* @param bucketName 要删除的存储桶名称。
* @return 如果存储桶成功删除,则返回true;如果存储桶不存在,则返回true;否则返回false。
*/
@Override
public boolean removeBucket(String bucketName) {
if (!ifExistsBucket(bucketName)) {
return true;
}
try {
minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());
} catch (ErrorResponseException | InsufficientDataException | InternalException | InvalidKeyException | InvalidResponseException | IOException | NoSuchAlgorithmException | ServerException | XmlParserException e) {
e.printStackTrace();
}
return !ifExistsBucket(bucketName);
}
/**
* 列出MinIO服务器上所有存在的存储桶。
*
* @return 返回一个包含所有存储桶信息的列表。
*/
@Override
public List<Bucket> alreadyExistBuckets() {
List<Bucket> buckets = null;
try {
buckets = minioClient.listBuckets();
} catch (ErrorResponseException | InsufficientDataException | InternalException | InvalidKeyException | InvalidResponseException | IOException | NoSuchAlgorithmException | ServerException | XmlParserException e) {
e.printStackTrace();
}
return buckets;
}
/**
* 检查指定的文件是否存在于存储桶中。
*
* @param bucketName 存储桶名称。
* @param filename 要检查的文件名。
* @param recursive 是否递归搜索子目录。
* @return 如果文件存在,则返回true;否则返回false。
*/
@Override
public boolean fileifexist(String bucketName, String filename, boolean recursive) {
boolean flag = false;
Iterable<Result<Item>> results = minioClient.listObjects(ListObjectsArgs.builder()
.bucket(bucketName)
.prefix(filename)
.recursive(recursive)
.maxKeys(1000)
.build());
for (Result<Item> result : results) {
try {
Item item = result.get();
if (item.objectName().equals(filename)) {
flag = true;
break;
}
} catch (ErrorResponseException | InsufficientDataException | InternalException | InvalidKeyException | InvalidResponseException | IOException | NoSuchAlgorithmException | ServerException | XmlParserException e) {
e.printStackTrace();
}
}
return flag;
}
/**
* 列出存储桶中所有对象,可指定前缀和是否递归搜索子目录。
*
* @param bucketName 存储桶名称。
* @param predir 前缀过滤器。
* @param recursive 是否递归搜索子目录。
* @return 返回一个包含所有匹配对象的结果列表。
*/
@Override
public List<Result<Item>> listObjects(String bucketName, String predir, boolean recursive) {
Iterable<Result<Item>> results = minioClient.listObjects(ListObjectsArgs.builder()
.bucket(bucketName)
.prefix(predir)
.recursive(recursive)
.maxKeys(1000)
.build());
List<Result<Item>> list = new ArrayList<>();
results.forEach(list::add);
return list;
}
/**
* 构建存储桶中对象的ComposeSource列表,用于复合对象操作。
*
* @param bucketName 存储桶名称。
* @param predir 前缀过滤器。
* @return 返回一个包含所有匹配对象的ComposeSource列表。
*/
@Override
public List<ComposeSource> listObjects(String bucketName, String predir) {
Iterable<Result<Item>> results = minioClient.listObjects(ListObjectsArgs.builder()
.bucket(bucketName)
.prefix(predir)
.recursive(true)
.maxKeys(1000)
.build());
List<Result<Item>> list = new ArrayList<>();
results.forEach(list::add);
List<ComposeSource> sources = new ArrayList<>();
for (Result<Item> itemResult : list) {
try {
sources.add(ComposeSource.builder().bucket(bucketName).object(itemResult.get().objectName()).build());
} catch (ErrorResponseException | InsufficientDataException | InternalException | InvalidKeyException | InvalidResponseException | IOException | NoSuchAlgorithmException | ServerException | XmlParserException e) {
e.printStackTrace();
}
}
return sources;
}
/**
* 复制一个对象到新的存储桶或新的对象名称。
*
* @param pastBucket 原始存储桶名称
* @param pastObject 原始对象名称
* @param newBucket 新的存储桶名称
* @param newObject 新的对象名称
* @return 如果复制成功,则返回true;否则返回false。
*/
@Override
public boolean copyObject(String pastBucket, String pastObject, String newBucket, String newObject) {
try {
ObjectWriteResponse response = minioClient.copyObject(
CopyObjectArgs.builder()
.bucket(newBucket)
.object(newObject)
.source(
CopySource.builder()
.bucket(pastBucket)
.object(pastObject)
.build())
.build());
} catch (ErrorResponseException e) {
e.printStackTrace();
return false;
} catch (InsufficientDataException | InternalException | InvalidKeyException | InvalidResponseException | IOException | NoSuchAlgorithmException | ServerException | XmlParserException e) {
e.printStackTrace();
}
return true;
}
/**
* 下载存储桶中的对象到本地文件系统。
*
* @param bucketName 存储桶名称
* @param objectName 对象名称
* @param targetPath 本地目标路径
* @return 如果下载成功,则返回true;否则返回false。
*/
@Override
public boolean downObject(String bucketName, String objectName, String targetPath) {
try {
if ("".equals(objectName) || null == objectName) {
throw new RuntimeException("检查电子文件FilePath是否为空,下载目标位置为:" + targetPath);
}
minioClient.downloadObject(
DownloadObjectArgs.builder()
.bucket(bucketName)
.object(objectName)
.filename(targetPath) //download local path
.build());
} catch (ErrorResponseException e) {
e.printStackTrace();
return false;
} catch (InsufficientDataException | InternalException | InvalidKeyException | InvalidResponseException | IOException | NoSuchAlgorithmException | ServerException | XmlParserException e) {
e.printStackTrace();
}
return true;
}
/**
* 获取存储桶中对象的预签名URL(GET方法)。
*
* @param bucketName 存储桶名称
* @param object 对象名称
* @param expire 过期时间(分钟)
* @return 预签名URL,如果发生错误则返回null。
*/
@Override
public String presignedURLofObject(String bucketName, String object, int expire) {
String url = null;
try {
url = minioClient.getPresignedObjectUrl(
GetPresignedObjectUrlArgs.builder()
.method(Method.GET)
.bucket(bucketName)
.object(object)
.expiry(expire, TimeUnit.MINUTES)
.build());
} catch (ErrorResponseException | InsufficientDataException | InternalException | InvalidKeyException | InvalidResponseException | IOException | NoSuchAlgorithmException | XmlParserException | ServerException e) {
e.printStackTrace();
}
return url;
}
/**
* 获取存储桶中对象的预签名URL,允许设置额外的查询参数。
*
* @param bucketName 存储桶名称
* @param object 对象名称
* @param expire 过期时间(分钟)
* @param map 额外的查询参数
* @return 预签名URL,如果发生错误则返回空字符串。
*/
@Override
public String presignedURLofObject(String bucketName, String object, int expire, Map<String, String> map) {
map.put("response-content-type", "application/json");
String presignedObjectUrl = "";
try {
presignedObjectUrl = minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
.bucket(bucketName)
.object(object)
.method(Method.GET)
.expiry(expire, TimeUnit.MINUTES)
.extraQueryParams(map)
.build());
} catch (ErrorResponseException | InsufficientDataException | InternalException | InvalidKeyException | InvalidResponseException | IOException | NoSuchAlgorithmException | XmlParserException | ServerException e) {
e.printStackTrace();
}
return presignedObjectUrl;
}
/**
* 删除存储桶中的对象。
*
* @param bucketName 存储桶名称
* @param object 对象名称
* @return 如果删除成功,则返回true;否则返回false。
*/
@Override
public boolean deleteObject(String bucketName, String object) {
try {
minioClient.removeObject(RemoveObjectArgs.builder()
.bucket(bucketName)
.object(object)
.build());
} catch (ErrorResponseException e) {
e.printStackTrace();
return false;
} catch (InsufficientDataException | InternalException | InvalidKeyException | InvalidResponseException | IOException | NoSuchAlgorithmException | ServerException | XmlParserException e) {
e.printStackTrace();
}
return true;
}
/**
* 将本地文件上传至MinIO存储桶。
*
* @param bucketName 存储桶名称
* @param targetObject 目标对象名称
* @param sourcePath 源文件路径
* @return 如果上传成功,则返回true;否则返回false。
*/
@Override
public boolean uploadObject(String bucketName, String targetObject, String sourcePath) {
try {
minioClient.uploadObject(UploadObjectArgs.builder()
.bucket(bucketName)
.object(targetObject)
.filename(sourcePath)
.build());
} catch (ErrorResponseException | InsufficientDataException | InternalException | InvalidKeyException | InvalidResponseException | IOException | NoSuchAlgorithmException | ServerException | XmlParserException e) {
e.printStackTrace();
return false;
}
return true;
}
/**
* 将输入流数据写入MinIO存储桶。
*
* @param bucketName 存储桶名称
* @param object 对象名称
* @param inputStream 输入流
* @return 如果写入成功,则返回true;否则返回false。
*/
@Override
public boolean putObject(String bucketName, String object, InputStream inputStream) {
try {
minioClient.putObject(PutObjectArgs.builder()
.bucket(bucketName)
.object(object)
.stream(inputStream, -1, 10485760)
.build());
} catch (ErrorResponseException | InsufficientDataException | InternalException | InvalidKeyException | InvalidResponseException | IOException | NoSuchAlgorithmException | ServerException | XmlParserException e) {
e.printStackTrace();
return false;
}
return true;
}
/**
* 将带有标签的输入流数据写入MinIO存储桶。
*
* @param bucketName 存储桶名称
* @param object 对象名称
* @param inputStream 输入流
* @param tags 对象标签
* @return 如果写入成功,则返回true;否则返回false。
*/
@Override
public boolean putObject(String bucketName, String object, InputStream inputStream, Map<String, String> tags) {
try {
minioClient.putObject(PutObjectArgs.builder()
.bucket(bucketName)
.object(object)
.stream(inputStream, -1, 10485760)
.tags(tags)
.build());
} catch (ErrorResponseException | InsufficientDataException | InternalException | InvalidKeyException | InvalidResponseException | IOException | NoSuchAlgorithmException | ServerException | XmlParserException e) {
e.printStackTrace();
return false;
}
return true;
}
/**
* 从MinIO存储桶获取对象。
*
* @param bucketName 存储桶名称
* @param object 对象名称
* @return 返回对象响应信息,如果发生错误则返回null。
*/
@Override
public GetObjectResponse getObject(String bucketName, String object) {
GetObjectResponse object1 = null;
try {
object1 = minioClient.getObject(GetObjectArgs.builder()
.bucket(bucketName)
.object(object)
.build());
} catch (ErrorResponseException | InsufficientDataException | InternalException | InvalidKeyException | InvalidResponseException | IOException | NoSuchAlgorithmException | ServerException | XmlParserException e) {
e.printStackTrace();
}
return object1;
}
/**
* 获取对象的标签信息。
*
* @param bucketName 存储桶名称
* @param object 对象名称
* @return 返回对象的标签映射,如果发生错误则返回null。
*/
@Override
public Map<String, String> getTags(String bucketName, String object) {
Map<String, String> map = new HashMap<>();
try {
Tags objectTags = minioClient.getObjectTags(GetObjectTagsArgs.builder()
.bucket(bucketName)
.object(object)
.build());
map = objectTags.get();
} catch (ErrorResponseException | InsufficientDataException | InternalException | InvalidKeyException | InvalidResponseException | IOException | NoSuchAlgorithmException | ServerException | XmlParserException e) {
e.printStackTrace();
return null;
}
return map;
}
/**
* 向对象添加或更新标签。
*
* @param bucketName 存储桶名称
* @param object 对象名称
* @param addTags 要添加或更新的标签映射
* @return 如果操作成功,则返回true;否则返回false。
*/
@Override
public boolean addTags(String bucketName, String object, Map<String, String> addTags) {
Map<String, String> oldtags = new HashMap<>();
Map<String, String> newTags = new HashMap<>();
try {
oldtags = getTags(bucketName, object);
if (oldtags.size() > 0) {
newTags.putAll(oldtags);
}
if (addTags != null && addTags.size() > 0) {
newTags.putAll(addTags);
}
minioClient.setObjectTags(SetObjectTagsArgs.builder()
.bucket(bucketName)
.object(object)
.tags(newTags)
.build());
return true;
} catch (ErrorResponseException | InsufficientDataException | InternalException | InvalidKeyException | InvalidResponseException | IOException | NoSuchAlgorithmException | ServerException | XmlParserException e) {
e.printStackTrace();
return false;
}
}
/**
* 获取对象的状态信息。
*
* @param bucketName 存储桶名称
* @param object 对象名称
* @return 返回对象状态信息,如果发生错误则返回null。
*/
@Override
public StatObjectResponse statObject(String bucketName, String object) {
StatObjectResponse statObject = null;
try {
statObject =
minioClient.statObject(
StatObjectArgs.builder()
.bucket(bucketName)
.object(object)
.build());
} catch (ErrorResponseException | InsufficientDataException | InternalException | InvalidKeyException | InvalidResponseException | IOException | NoSuchAlgorithmException | ServerException | XmlParserException e) {
e.printStackTrace();
}
return statObject;
}
/**
* 判断存储桶中是否存在指定对象。
*
* @param bucketName 存储桶名称
* @param objectName 对象名称
* @return 如果存在,则返回true;否则返回false。
*/
@Override
public boolean ifExistObject(String bucketName, String objectName) {
return listObjects(bucketName, objectName, true).size() >= 1;
}
/**
* 从元数据存储桶中获取与特定对象相关的元数据对象名。
*
* @param objectName 原始对象名称
* @return 返回编码后的元数据对象名,如果没有找到对应的元数据则返回其文件名。
*/
@Override
public String getMetaNameFromOther(String objectName) {
String metaobject = "";
List<Result<Item>> results = listObjects(BucketName.METADATA, FileUtil.getPreMeta(objectName), true);
if (results.size() == 1) {
try {
metaobject = results.get(0).get().objectName();
Map<String, String> tags = getTags(BucketName.METADATA, metaobject);
String s = tags.get(ObjectTags.FILENAME);
// 解码后再编码以确保正确处理特殊字符
// URLDecoder.decode(s,"UTF-8");
return URLEncoder.encode(s, "UTF-8");
} catch (ErrorResponseException | InsufficientDataException | InternalException | InvalidKeyException | InvalidResponseException | IOException | NoSuchAlgorithmException | ServerException | XmlParserException e) {
e.printStackTrace();
}
}
return FileUtil.getFileName(metaobject);
}
/**
* 修改对象的标签信息。
*
* @param object 对象名称
* @param tag 新的标签值
* @return 如果修改成功,则返回true;否则返回false。
*/
@Override
public boolean changeTag(String object, String tag) {
try {
Map<String, String> map = minioClient.getObjectTags(GetObjectTagsArgs.builder()
.bucket(BucketName.METADATA)
.object(object)
.build()).get();
Map<String, String> map1 = new HashMap<>();
tag = tag + FileUtil.getSuffix(object);
map1.put(ObjectTags.FILENAME, tag);
map1.put(ObjectTags.OPERATOR, map.get(ObjectTags.OPERATOR));
minioClient.setObjectTags(SetObjectTagsArgs.builder()
.bucket(BucketName.METADATA)
.object(object)
.tags(map1)
.build());
return true;
} catch (ErrorResponseException | InsufficientDataException | InternalException | InvalidKeyException | InvalidResponseException | IOException | NoSuchAlgorithmException | ServerException | XmlParserException e) {
e.printStackTrace();
return false;
}
}
/**
* 设置存储桶的访问策略为公开访问。
*
* @param bucketName 存储桶名称
*/
@Override
public void BucketAccessPublic(String bucketName) {
String config = "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Action\":[\"s3:ListBucketMultipartUploads\",\"s3:GetBucketLocation\",\"s3:ListBucket\"],\"Resource\":[\"arn:aws:s3:::" + bucketName + "\"]},{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Action\":[\"s3:ListMultipartUploadParts\",\"s3:PutObject\",\"s3:AbortMultipartUpload\",\"s3:DeleteObject\",\"s3:GetObject\"],\"Resource\":[\"arn:aws:s3:::" + bucketName + "/*\"]}]}";
try {
minioClient.setBucketPolicy(SetBucketPolicyArgs.builder().bucket(bucketName).config(config).build());
} catch (ErrorResponseException | InsufficientDataException | InternalException | InvalidKeyException | InvalidResponseException | IOException | NoSuchAlgorithmException | ServerException | XmlParserException e) {
e.printStackTrace();
}
}
}