文章目录
- 安装
- Docker安装
- Docker-compose安装
- SpringBoot集成
- 引入依赖
- 初始化客户端
- 存储桶的CRUD
- 存储桶的文件操作
- 存储桶生命周期配置
安装
Docker安装
docker run -p 9000:9000 -p 9090:9090 \
--net=host \
--name minio \
-d --restart=always \
-e "MINIO_ACCESS_KEY=admin" \
-e "MINIO_SECRET_KEY=123456" \
-v /usr/local/minio/data:/data \
minio/minio server \
/data --console-address ":9090" -address ":9000"
Docker-compose安装
version: '3'
services:
minio:
image: minio/minio
restart: always
environment:
- MINIO_ACCESS_KEY=admin
- MINIO_SECRET_KEY=123456
command: server /data --console-address ":9090" -address ":9000"
container_name: minio
hostname: minio
volumes:
- /usr/local/minio/data:/data
logging:
driver: json-file
options:
max-size: '20m'
max-file: '20'
network_mode: host
SpringBoot集成
引入依赖
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.3.7</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.8.1</version>
</dependency>
初始化客户端
@Component
@ConfigurationProperties(prefix = "minio")
@Slf4j
public class MinioService implements InitializingBean {
/**
* MinIO的API地址
*/
@Setter
private String endpoint;
/**
* 用户名
*/
@Setter
private String accessKey;
/**
* 密钥
*/
@Setter
private String secretKey;
/**
* 自定义域名(非必须)
*/
@Setter
private String customDomain;
/**
* 存储桶名称,默认微服务单独一个存储桶
*/
@Setter
private String defaultBucket;
private MinioClient minioClient;
// 初始化客户端
@Override
public void afterPropertiesSet() {
log.info("初始化 MinIO 客户端...");
Assert.notBlank(endpoint, "MinIO endpoint不能为空");
Assert.notBlank(accessKey, "MinIO accessKey不能为空");
Assert.notBlank(secretKey, "MinIO secretKey不能为空");
this.minioClient = MinioClient.builder()
//.endpoint(endpoint, 443, true)
.endpoint(endpoint)
.credentials(accessKey, secretKey)
.build();
}
}
存储桶的CRUD
存储桶是否存在
public boolean bucketExists(BucketExistsArgs args);
创建存储桶
/**
* 创建存储桶(存储桶不存在)
*
* @param bucketName
*/
@SneakyThrows
public void createBucketIfAbsent(String bucketName) {
BucketExistsArgs bucketExistsArgs = BucketExistsArgs.builder()
.bucket(bucketName)
.build();
if (!minioClient.bucketExists(bucketExistsArgs)) {
MakeBucketArgs makeBucketArgs = MakeBucketArgs.builder()
.bucket(bucketName)
.build();
minioClient.makeBucket(makeBucketArgs);
// 设置存储桶访问权限为PUBLIC, 如果不配置,则新建的存储桶默认是PRIVATE,则存储桶文件会拒绝访问 Access Denied
SetBucketPolicyArgs setBucketPolicyArgs = SetBucketPolicyArgs.builder()
.bucket(bucketName)
.config(publicBucketPolicy(bucketName).toString())
.build();
minioClient.setBucketPolicy(setBucketPolicyArgs);
}
}
/**
* PUBLIC桶策略
* 如果不配置,则新建的存储桶默认是PRIVATE,则存储桶文件会拒绝访问 Access Denied
*
* @param bucketName
* @return
*/
private static StringBuilder publicBucketPolicy(String bucketName) {
/**
* AWS的S3存储桶策略
* Principal: 生效用户对象
* Resource: 指定存储桶
* Action: 操作行为
*/
StringBuilder builder = new StringBuilder();
builder.append("{\"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 + "/*\"]}]}");
return builder;
}
查询存储桶信息列表
public List<Bucket> listBuckets();
删除一个空桶
public void removeBucket(RemoveBucketArgs args)
存储桶的文件操作
/**
* 上传文件对象(默认存储桶)
*
* @param file MultipartFile文件对象
* @return
*/
public String putObject(MultipartFile file) {
String fileUrl = putObject(file, defaultBucket);
return fileUrl;
}
/**
* 上传文件对象
*
* @param file MultipartFile文件对象
* @param bucketName 存储桶名称
* @return
*/
@SneakyThrows
public String putObject(MultipartFile file, String bucketName) {
// 存储桶名称为空则使用默认的存储桶
if (StrUtil.isBlank(bucketName)) {
bucketName = defaultBucket;
}
createBucketIfAbsent(bucketName);
String suffix = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".") + 1);
String fileName = IdUtil.simpleUUID() + "." + suffix;
InputStream inputStream = file.getInputStream();
PutObjectArgs putObjectArgs = PutObjectArgs.builder()
.bucket(bucketName)
.object(fileName)
.contentType(file.getContentType())
.stream(inputStream, inputStream.available(), -1)
.build();
minioClient.putObject(putObjectArgs);
String fileUrl;
if (StrUtil.isBlank(customDomain)) { // 没有自定义文件路径域名
GetPresignedObjectUrlArgs getPresignedObjectUrlArgs = GetPresignedObjectUrlArgs.builder()
.bucket(bucketName)
.object(fileName)
.method(Method.GET)
.build();
fileUrl = minioClient.getPresignedObjectUrl(getPresignedObjectUrlArgs);
fileUrl = fileUrl.substring(0, fileUrl.indexOf("?"));
} else { // 自定义文件路径域名,Nginx配置方向代理转发MinIO
fileUrl = customDomain +'/'+ bucketName + "/" + fileName;
}
return fileUrl;
}
public void removeObject(String bucket, String fileName) throws Exception {
RemoveObjectArgs removeObjectArgs = RemoveObjectArgs.builder()
.bucket(bucket)
.object(fileName)
.build();
minioClient.removeObject(removeObjectArgs);
}
存储桶生命周期配置
/*
* oss设置生命周期规则
* 存储桶生命周期配置: public void setBucketLifecycle(SetBucketLifecycleArgs args)
* 获取桶的生命周期配置: public LifecycleConfiguration getBucketLifecycle(GetBucketLifecycleArgs args)
*
* */
@SneakyThrows
public void setBucketLifecycle(String bucketName, String ruleId, String prefix, Integer days ) {
List<LifecycleRule> rules = new LinkedList<>();
rules.add(
new LifecycleRule(
Status.ENABLED,
null,
new Expiration((ZonedDateTime) null, days, null),
new RuleFilter(prefix),
ruleId,
null,
null,
null));
LifecycleConfiguration config = new LifecycleConfiguration(rules);
minioClient.setBucketLifecycle(
SetBucketLifecycleArgs.builder().bucket(bucketName).config(config).build());
}
- oss设置生命周期规则
- 存储桶生命周期配置: public void setBucketLifecycle(SetBucketLifecycleArgs args)
- 获取桶的生命周期配置: public LifecycleConfiguration getBucketLifecycle(GetBucketLifecycleArgs args)
- LifecycleRule 的配置参数
- status:设置规则开启还是关闭状态。
- AbortIncompleteMultipartUpload(int daysAfterInitiation):设置分片在距最后修改时间30天后过期。
- Expiration(ZonedDateTime date, Integer days, Boolean expiredObjectDeleteMarker) :
指定日期
或天数过期
,标志删除or彻底删除
- RuleFilter(AndOperator andOperator,String prefix,Tag tag) :依据
前缀删除(前缀即桶内的文件夹名)
或者tag标志删除
- id,一个桶可以设置多个rule
- NoncurrentVersionExpiration(int noncurrentDays):设置非当前版本的Object
- NoncurrentVersionTransition(int noncurrentDays,String storageClass): 设置非当前版本的Object距最后修改时间90天之后转为低频访问类型、归档类型。非当前版本对象何时进行存储类型的转换和转换的存储类型,待确认storageClass
你知道的越多,你不知道的越多。