MinIO是一款开源的对象存储服务器。本项目基于Spring Boot自动配置MinioClient,开发MinIO客户端程序更方便。
项目源码:Gitee
简介
megrez.boot.autoconfigure.minio.MinioProperties属性配置
@Data
@ConfigurationProperties(prefix = "minio")
public class MinioProperties {
/** 服务器参数 */
private Server server = new Server();
/** 连接参数 */
private Connection connection = new Connection();
/** 连接参数 */
private Proxy proxy = new Proxy();
@Data
public static class Proxy {
private String host;
private Integer port;
}
@Data
public static class Connection {
/**
* Define the connect timeout for the Minio Client.
*/
private Duration connectTimeout = Duration.ofSeconds(10);
/**
* Define the write timeout for the Minio Client.
*/
private Duration writeTimeout = Duration.ofSeconds(60);
/**
* Define the read timeout for the Minio Client.
*/
private Duration readTimeout = Duration.ofSeconds(10);
}
@Data
public static class Server {
/**
* URL for Minio instance. Can include the HTTP scheme. Must include the port.
* If the port is not provided, then the port of the HTTP is taken.
*/
private String endpoint = "127.0.0.1";
private Integer port = 9000;
/**
* Access key (login) on Minio instance
*/
private String accessKey = "admin";
/**
* Secret key (password) on Minio instance
*/
private String secretKey = "admin";
/**
* If the scheme is not provided in {@code url} property, define if the
* connection is done via HTTP or HTTPS.
*/
private boolean secure = false;
}
}
megrez.boot.autoconfigure.minio.MinioAutoConfiguration自动配置
@Slf4j
@Configuration
@ConditionalOnClass(MinioClient.class)
@EnableConfigurationProperties(MinioProperties.class)
public class MinioAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public MinioClient minioClient(MinioProperties properties, ObjectProvider<MinioConfigurer> configurers) {
final Server server = properties.getServer();
final Connection connection = properties.getConnection();
final Proxy proxy = properties.getProxy();
log.info("Initializing MinioClient [{}:{}]", server.getEndpoint(), server.getPort());
final MinioClient.Builder builder = MinioClient.builder()
.endpoint(server.getEndpoint(), server.getPort(), server.isSecure())
.credentials(server.getAccessKey(), server.getSecretKey());
if (StringUtils.hasText(proxy.getHost())) {
log.info("Http proxy enabled [{}:{}]}", proxy.getHost(), proxy.getPort());
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.proxy(new java.net.Proxy(java.net.Proxy.Type.HTTP,
new InetSocketAddress(proxy.getHost(), proxy.getPort())))
.build();
builder.httpClient(okHttpClient);
}
// 自定义配置处理
configurers.forEach(configurer -> configurer.configure(builder));
MinioClient minioClient = builder.build();
minioClient.setTimeout(
connection.getConnectTimeout().toMillis(),
connection.getWriteTimeout().toMillis(),
connection.getReadTimeout().toMillis());
return minioClient;
}
@Bean
@ConditionalOnMissingBean
public MinioObjectClient minioObjectClient(MinioClient minioClient) {
return new MinioObjectClient(minioClient);
}
@Bean
@ConditionalOnMissingBean
public MinioBucketClient minioBucketClient(MinioClient minioClient) {
return new MinioBucketClient(minioClient);
}
}
megrez.boot.autoconfigure.minio.MinioObjectClient对象操作服务
@RequiredArgsConstructor
public class MinioObjectClient {
private final MinioClient client;
/**
* 上传对象流
*
* @param bucketName 桶
* @param objectName 对象
* @param stream 流
* @param consumer builder消费
* @return
*/
public ObjectWriteResponse putObject(String bucketName, String objectName, InputStream stream,
Consumer<PutObjectArgs.Builder> consumer) {
try {
PutObjectArgs.Builder builder = PutObjectArgs.builder()
.bucket(bucketName)
.object(objectName)
.stream(stream, stream.available(), -1);
if (consumer != null) {
consumer.accept(builder);
}
return client.putObject(builder.build());
} catch (Exception e) {
throw new MinioRuntimeException(e);
}
}
/**
* 上传对象流
*
* @param bucketName 桶
* @param objectName 对象
* @param stream 流
* @return
*/
public ObjectWriteResponse putObject(String bucketName, String objectName, InputStream stream) {
return putObject(bucketName, objectName, stream, null);
}
/**
* 获取对象流
*
* @param bucketName 桶
* @param objectName 对象
* @param consumer builder消费
* @return
*/
public GetObjectResponse getObject(String bucketName, String objectName, Consumer<GetObjectArgs.Builder> consumer) {
try {
GetObjectArgs.Builder builder = GetObjectArgs.builder()
.bucket(bucketName)
.object(objectName);
if (consumer != null) {
consumer.accept(builder);
}
return client.getObject(builder.build());
} catch (Exception e) {
throw new MinioRuntimeException(e);
}
}
/**
* 获取对象流
*
* @param bucketName 桶
* @param objectName 对象
* @return
*/
public GetObjectResponse getObject(String bucketName, String objectName) {
return getObject(bucketName, objectName, null);
}
/**
* 获取对象流-支持端点续传
*
* @param bucketName 桶
* @param objectName 对象
* @param offset 起始字节的位置
* @param length 要读取的长度 (可选,如果无值则代表读到对象结尾)
* @return
*/
public GetObjectResponse getObject(String bucketName, String objectName, Long offset, Long length) {
return getObject(bucketName, objectName, builder -> {
builder.offset(offset);
if (length != null) {
builder.length(length);
}
});
}
/**
* 获取对象信息和对象的元数据
*
* @param bucketName 桶
* @param objectName 对象
* @param consumer builder消费
* @return
*/
public StatObjectResponse statObject(String bucketName, String objectName,
Consumer<StatObjectArgs.Builder> consumer) {
try {
StatObjectArgs.Builder builder = StatObjectArgs.builder()
.bucket(bucketName)
.object(objectName);
if (consumer != null) {
consumer.accept(builder);
}
return client.statObject(builder.build());
} catch (Exception e) {
throw new MinioRuntimeException(e);
}
}
/**
* 获取对象信息和对象的元数据
*
* @param bucketName 桶
* @param objectName 对象
* @return
*/
public StatObjectResponse statObject(String bucketName, String objectName) {
return statObject(bucketName, objectName, null);
}
/**
* 对象是否存在
*
* @param bucketName 桶
* @param objectName 对象
* @return
*/
public boolean existObject(String bucketName, String objectName) {
try {
StatObjectResponse response = statObject(bucketName, objectName, null);
return response != null;
} catch (MinioRuntimeException e) {
return false;
}
}
/**
* 获取对象的元数据
*
* @param bucketName 桶
* @param objectName 对象
* @return
*/
public Map<String, String> getObjectUserMetadata(String bucketName, String objectName) {
return statObject(bucketName, objectName).userMetadata();
}
/**
* 获取预签名对象网址, 默认Method.GET方法,分享链接地址失效时间为7天
*
* @param bucketName 桶
* @param objectName 对象
* @param consumer bilder消费
* @return
*/
public String getPresignedObjectUrl(String bucketName, String objectName,
Consumer<GetPresignedObjectUrlArgs.Builder> consumer) {
try {
GetPresignedObjectUrlArgs.Builder builder = GetPresignedObjectUrlArgs.builder()
.bucket(bucketName)
.object(objectName)
.method(Method.GET);
if (consumer != null) {
consumer.accept(builder);
}
return client.getPresignedObjectUrl(builder.build());
} catch (Exception e) {
throw new MinioRuntimeException(e);
}
}
/**
*
* @param bucketName 桶
* @param objectName 对象
* @param method 方法, GET, HEAD, POST, PUT, DELETE;
* @param expiry 失效时间(以秒为单位),默认是7天,不得大于七天
* @return
*/
public String getPresignedObjectUrl(String bucketName, String objectName, Method method, Duration expiry) {
return getPresignedObjectUrl(bucketName, objectName, builder -> {
builder.method(method);
if (expiry != null) {
builder.expiry((int) expiry.toSeconds());
}
});
}
/**
* 根据对象前缀查询对象
*
* @param bucketName 桶
* @param consumer builder消费
* @return
*/
public List<Item> listObjects(String bucketName, Consumer<ListObjectsArgs.Builder> consumer) {
try {
ListObjectsArgs.Builder builder = ListObjectsArgs.builder()
.bucket(bucketName);
if (consumer != null) {
consumer.accept(builder);
}
Iterable<Result<Item>> iterable = client.listObjects(builder.build());
return StreamSupport
.stream(iterable.spliterator(), true)
.map(itemResult -> {
try {
return itemResult.get();
} catch (InvalidKeyException | ErrorResponseException | IllegalArgumentException
| InsufficientDataException | InternalException | InvalidResponseException
| NoSuchAlgorithmException | ServerException | XmlParserException | IOException e) {
throw new MinioRuntimeException(e);
}
})
.collect(Collectors.toList());
} catch (Exception e) {
throw new MinioRuntimeException(e);
}
}
/**
*
* 根据对象前缀查询对象
*
* @param bucketName 桶
* @param prefix 桶中对象的前缀 默认 空字符串
* @param recursive 是否递归子目录
* @return
*/
public List<Item> listObjects(String bucketName, String prefix, Boolean recursive) {
return listObjects(bucketName, builder -> {
if (StringUtils.hasText(prefix)) {
builder.prefix(prefix);
}
if (recursive != null) {
builder.recursive(recursive);
}
});
}
/**
* 组合源对象列表, 通过使用服务器端副本组合来自不同源对象的数据来创建对象,服务器上已存在的对象列表再次组合成一个对象
*
* @param bucketName 桶
* @param objectName 对象
* @param sourceObjectList 组合组合的源对象列表
* @param consumer builder消费
* @return
*/
public ObjectWriteResponse composeObject(String bucketName, String objectName, List<ComposeSource> sourceObjectList,
Consumer<ComposeObjectArgs.Builder> consumer) {
try {
ComposeObjectArgs.Builder builder = ComposeObjectArgs.builder()
.bucket(bucketName)
.object(objectName)
.sources(sourceObjectList);
if (consumer != null) {
consumer.accept(builder);
}
return client.composeObject(builder.build());
} catch (Exception e) {
throw new MinioRuntimeException(e);
}
}
/**
*
* 组合源对象列表, 通过使用服务器端副本组合来自不同源对象的数据来创建对象,服务器上已存在的对象列表再次组合成一个对象
*
* @param bucketName 桶
* @param objectName 对象
* @param sourceObjectList 组合组合的源对象列表
* @return
*/
public ObjectWriteResponse composeObject(String bucketName, String objectName,
List<ComposeSource> sourceObjectList) {
return composeObject(bucketName, objectName, sourceObjectList, null);
}
/**
* 复制对象
*
* @param bucketName 桶
* @param objectName 对象
* @param source 源对象
* @param consumer builder消费
* @return
*/
public ObjectWriteResponse copyObject(String bucketName, String objectName, CopySource source,
Consumer<CopyObjectArgs.Builder> consumer) {
try {
CopyObjectArgs.Builder builder = CopyObjectArgs.builder()
.bucket(bucketName)
.object(objectName)
.source(source);
if (consumer != null) {
consumer.accept(builder);
}
return client.copyObject(builder.build());
} catch (Exception e) {
throw new MinioRuntimeException(e);
}
}
/**
*
* 复制对象
*
* @param bucketName 桶
* @param objectName 对象
* @param source 源对象
* @return
*/
public ObjectWriteResponse copyObject(String bucketName, String objectName, CopySource source) {
return copyObject(bucketName, objectName, source, null);
}
/**
* 设置对象的标签
*
* @param bucketName 桶
* @param objectName 对象
* @param tags 标签
* @param consumer builder消费
*/
public void setObjectTags(String bucketName, String objectName, Tags tags,
Consumer<SetObjectTagsArgs.Builder> consumer) {
try {
SetObjectTagsArgs.Builder builder = SetObjectTagsArgs.builder()
.bucket(bucketName)
.object(objectName)
.tags(tags);
if (consumer != null) {
consumer.accept(builder);
}
client.setObjectTags(builder.build());
} catch (Exception e) {
throw new MinioRuntimeException(e);
}
}
/**
* 设置对象的标签
*
* @param bucketName 桶
* @param objectName 对象
* @param tags 标签
*/
public void setObjectTags(String bucketName, String objectName, Tags tags) {
setObjectTags(bucketName, objectName, tags, null);
}
/**
* 获取对象的标签
*
* @param bucketName 桶
* @param objectName 对象
* @param consumer builder消费
* @return
*/
public Tags getObjectTags(String bucketName, String objectName, Consumer<GetObjectTagsArgs.Builder> consumer) {
try {
GetObjectTagsArgs.Builder builder = GetObjectTagsArgs.builder()
.bucket(bucketName)
.object(objectName);
if (consumer != null) {
consumer.accept(builder);
}
return client.getObjectTags(builder.build());
} catch (Exception e) {
throw new MinioRuntimeException(e);
}
}
/**
* 获取对象的标签
*
* @param bucketName 桶
* @param objectName 对象
* @return
*/
public Tags getObjectTags(String bucketName, String objectName) {
return getObjectTags(bucketName, objectName, null);
}
/**
* 删除对象标签
*
* @param bucketName 桶
* @param objectName 对象
* @param consumer builder消费
*/
public void deleteObjectTags(String bucketName, String objectName,
Consumer<DeleteObjectTagsArgs.Builder> consumer) {
try {
DeleteObjectTagsArgs.Builder builder = DeleteObjectTagsArgs.builder()
.bucket(bucketName)
.object(objectName);
if (consumer != null) {
consumer.accept(builder);
}
client.deleteObjectTags(builder.build());
} catch (Exception e) {
throw new MinioRuntimeException(e);
}
}
/**
* 删除对象标签
*
* @param bucketName 桶
* @param objectName 对象
*/
public void deleteObjectTags(String bucketName, String objectName) {
deleteObjectTags(bucketName, objectName, null);
}
/**
* 删除单个对象
*
* @param bucketName 桶
* @param objectName 对象
* @param consumer builder消费
*/
public void deleteObject(String bucketName, String objectName, Consumer<RemoveObjectArgs.Builder> consumer) {
try {
RemoveObjectArgs.Builder builder = RemoveObjectArgs.builder()
.bucket(bucketName)
.object(objectName);
if (consumer != null) {
consumer.accept(builder);
}
client.removeObject(builder.build());
} catch (Exception e) {
throw new MinioRuntimeException(e);
}
}
/**
*
* 删除单个对象
*
* @param bucketName 桶
* @param objectName 对象
*/
public void deleteObject(String bucketName, String objectName) {
deleteObject(bucketName, objectName, null);
}
/**
* 删除多个对象
*
* @param bucketName 桶
* @param objectNames 对象列表
* @param consumer builder消费
*/
public List<DeleteError> deleteObjects(String bucketName, List<DeleteObject> objectNames,
Consumer<RemoveObjectsArgs.Builder> consumer) {
try {
RemoveObjectsArgs.Builder builder = RemoveObjectsArgs.builder()
.bucket(bucketName)
.objects(objectNames);
if (consumer != null) {
consumer.accept(builder);
}
Iterable<Result<DeleteError>> iterable = client.removeObjects(builder.build());
return StreamSupport.stream(iterable.spliterator(), true).map(result -> {
try {
return result.get();
} catch (InvalidKeyException | ErrorResponseException | IllegalArgumentException
| InsufficientDataException | InternalException | InvalidResponseException
| NoSuchAlgorithmException | ServerException | XmlParserException | IOException e) {
throw new MinioRuntimeException(e);
}
}).collect(Collectors.toList());
} catch (Exception e) {
throw new MinioRuntimeException(e);
}
}
/**
* 删除多个对象
*
* @param bucketName 桶
* @param objectNames 对象列表
* @return
*/
public List<DeleteError> deleteObjects(String bucketName, List<DeleteObject> objectNames) {
return deleteObjects(bucketName, objectNames, null);
}
}
megrez.boot.autoconfigure.minio.MinioBucketClient桶操作服务
@RequiredArgsConstructor
public class MinioBucketClient {
private final MinioClient client;
/**
* 桶是否存在
*
* @param bucketName 桶名
* @param consumer builder消费
* @return
*/
public boolean bucketExists(String bucketName, Consumer<BucketExistsArgs.Builder> consumer) {
try {
BucketExistsArgs.Builder builder = BucketExistsArgs.builder()
.bucket(bucketName);
if (consumer != null) {
consumer.accept(builder);
}
return client.bucketExists(builder.build());
} catch (Exception e) {
throw new MinioRuntimeException(e);
}
}
/**
* 桶是否存在
*
* @param bucketName 桶名
* @return
*/
public boolean bucketExists(String bucketName) {
return bucketExists(bucketName, null);
}
/**
* 所有桶信息
*
* @return
*/
public List<Bucket> listBuckets() {
try {
return client.listBuckets();
} catch (Exception e) {
throw new MinioRuntimeException(e);
}
}
/**
* 创建桶
*
* @param bucketName 桶名
* @param consumer builder消费
*/
public void makeBucket(String bucketName, Consumer<MakeBucketArgs.Builder> consumer) {
try {
MakeBucketArgs.Builder builder = MakeBucketArgs.builder()
.bucket(bucketName);
if (consumer != null) {
consumer.accept(builder);
}
client.makeBucket(builder.build());
} catch (Exception e) {
throw new MinioRuntimeException(e);
}
}
/**
* 创建桶
*
* @param bucketName 桶名
*/
public void makeBucket(String bucketName) {
makeBucket(bucketName, null);
}
/**
* 获取存储桶中的对象锁定配置
*
* @param bucketName 桶名
* @param consumer builder消费
* @return
*/
public ObjectLockConfiguration getObjectLockConfiguration(String bucketName,
Consumer<GetObjectLockConfigurationArgs.Builder> consumer) {
try {
GetObjectLockConfigurationArgs.Builder builder = GetObjectLockConfigurationArgs.builder()
.bucket(bucketName);
if (consumer != null) {
consumer.accept(builder);
}
return client.getObjectLockConfiguration(builder.build());
} catch (Exception e) {
throw new MinioRuntimeException(e);
}
}
/**
* 获取存储桶中的对象锁定配置
*
* @param bucketName 桶名
* @return
*/
public ObjectLockConfiguration getObjectLockConfiguration(String bucketName) {
return getObjectLockConfiguration(bucketName, null);
}
}
完整实现参考源代码
还有更多的项目参考,megrez-oss是对象存储服务,基于本地文件系统的存储,或基于MinIO的存储服务