前言:Docker下Minio的一个总结和使用。
Minio 是一个基于Apache License v2.0开源协议的对象存储服务。它兼容亚马逊S3云存储服务接口,非常适合于存储大容量非结构化的数据,例如图片、视频、日志文件、备份数据和容器/虚拟机镜像等,而一个对象文件可以是任意大小,从几kb到最大5T不等。
一、Docker
中安装Minio
docker run \
# 映射端口
-p 9000:9000 -p 9001:9001 \
# 容器名
--name minio \
# 自启动
-d --restart=always \
# 登录的用户名
-e "MINIO_ACCESS_KEY=minio" \
# 登录的密码
-e "MINIO_SECRET_KEY=minio" \
# 数据卷挂载
-v /data/docker/minio/data:/data \
-v /data/docker/minio/config:/root/.minio \
# 指定Minio版本
minio/minio:RELEASE.2021-08-05T22-01-19Z server /data \
# minio默认启动是动态端口,设置固定端口
--address ':9000' --console-address ':9001'
二、在Java
中使用
导包
<!--minio依赖于okhttp,如果其他地方有冲突,需要改版本之前,先把okhttp注释掉-->
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.0.3</version>
</dependency>
Minio
初始化
import io.minio.MinioClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnableConfigurationProperties(MinioProp.class)
public class MinioConfig {
@Autowired
private MinioProp minioProp;
/**
* 获取MinioClient,初始化 Minio 客户端
*/
@Bean
public MinioClient minioClient() {
return MinioClient.builder()
.endpoint(minioProp.getEndpoint())
.credentials(minioProp.getAccessKey(), minioProp.getSecretKey())
.build();
}
}
MinioProp.java
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Data
@Component
@ConfigurationProperties(prefix = "minio")
public class MinioProp {
//连接地址
private String endpoint;
//用户名
private String accessKey;
//密码
private String secretKey;
//域名
private String filHost;
}
# minio的9000和9001要区分开:
# 默认9000是api的端口和9001是网页版,可以自己指定端口
minio.endpoint = http://127.0.0.1:9000
minio.accessKey = minio
minio.secretKey = minio
minio.filHost = http://127.0.0.1:9001
MinioUtil.java
import io.minio.*;
import io.minio.errors.*;
import io.minio.http.Method;
import io.minio.messages.Bucket;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Random;
/**
* 官方文档:https://docs.min.io/docs/java-client-api-reference.html
*/
@Slf4j
@Component
public class MinioUtil {
@Autowired
private MinioProp minioProp;
@Autowired
private MinioClient client;
/**
* 创建bucket
*/
public void createBucket(String bucketName) throws Exception {
if (!client.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build())) {
client.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
}
}
/**
* 获取全部bucket信息
*
* @return
*/
public List<Bucket> getAllBuckets() throws Exception {
return client.listBuckets();
}
/**
* 根据bucketName删除信息
*
* @param bucketName bucket名称
*/
public void removeBucket(String bucketName) throws Exception {
client.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());
}
/**
* 上传文件
*
* @param file
* @param bucketName
* @return
*/
public FileUploadResponse uploadFile(MultipartFile file, String bucketName) throws Exception {
//判断文件是否为空
if (null == file || 0 == file.getSize()) {
return null;
}
//判断存储桶是否存在 不存在则创建
createBucket(bucketName);
//文件名
String originalFilename = file.getOriginalFilename();
//新的文件名 = 存储桶文件名_时间戳.后缀名
assert originalFilename != null;
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
String fileName = bucketName + "_" +
System.currentTimeMillis() + "_" + format.format(new Date()) + "_" + new Random().nextInt(1000) +
originalFilename.substring(originalFilename.lastIndexOf("."));
//开始上传
client.putObject(
PutObjectArgs.builder().bucket(bucketName).object(fileName).stream(
file.getInputStream(), file.getSize(), -1)
.contentType(file.getContentType())
.build());
String url = minioProp.getEndpoint() + "/" + bucketName + "/" + fileName;
String urlHost = minioProp.getFilHost() + "/" + bucketName + "/" + fileName;
log.info("上传文件成功url :[{}], urlHost :[{}]", url, urlHost);
return new FileUploadResponse(url, urlHost, fileName);
}
/**
* 获取文件外链
*
* @param bucketName
* @param region
* @param fileName
* @return
*/
public String getObjectUrl(String bucketName, String region, String fileName) throws IOException, InvalidKeyException, InvalidResponseException, InsufficientDataException, NoSuchAlgorithmException, ServerException, InternalException, XmlParserException, ErrorResponseException {
return client.getPresignedObjectUrl(
GetPresignedObjectUrlArgs.builder()
.method(Method.GET)
.bucket(bucketName)
.region(region)
.object(fileName)
.build());
}
/**
* 删除⽂件
*
* @param bucketName bucket名称
* @param objectName ⽂件名称
*/
public void removeObject(String bucketName, String objectName) throws Exception {
client.removeObject(
RemoveObjectArgs.builder()
.bucket(bucketName)
.object(objectName)
.build()
);
}
}
test
@SpringBootTest
class SpringcloudApplicationTests {
@Autowired
MinioUtil minioUtil;
@Test
void contextLoads() throws Exception {
String bucketName = "iron-man";
//判断桶是否存在,不存在则创建
System.out.println("创建桶----------------");
minioUtil.createBucket(bucketName);
minioUtil.createBucket("image01");
//上传文件
System.out.println("上传文件---------------");
File file = new File("C:\\Users\\00\\Pictures\\登录\\t3.jpg");
InputStream inputStream = new FileInputStream(file);
//文件内容类型,可查看菜鸟教程来写:https://www.runoob.com/http/http-content-type.html
String contentType = "image/jpeg";
MultipartFile multipartFile = new MockMultipartFile(file.getName(),file.getName(), contentType, inputStream);
FileUploadResponse uploadFile = minioUtil.uploadFile(multipartFile, bucketName);
System.out.println(uploadFile);
String newFileName = uploadFile.getNewFileName();
//获取文件url访问路径
System.out.println("获取文件访问外链---------------");
String imageUrl = minioUtil.getObjectUrl("image", null, uploadFile.getNewFileName());
System.out.println(imageUrl);
//获取全部桶
System.out.println("全部桶name---------------");
List<Bucket> allBuckets = minioUtil.getAllBuckets();
allBuckets.stream().forEach(b -> {
System.out.println(b.name());
});
//删除桶
System.out.println("删除桶---------------");
minioUtil.removeBucket("image01");
//删除文件
System.out.println("删除文件---------------");
minioUtil.removeObject(bucketName, newFileName);
List<Bucket> allB = minioUtil.getAllBuckets();
allB.stream().forEach(b -> {
System.out.println(b.name());
});
}
}
结果
创建桶----------------
上传文件---------------
2021-12-10 10:45:31.660 INFO 49396 --- [ main] com.atliu.springcloud.minio.MinioUtil : 上传文件成功url :[http://127.0.0.1:9000/iron-man/iron-man_1639104331621_2021-12-10_573.jpg], urlHost :[http://127.0.0.1:9000/iron-man/iron-man_1639104331621_2021-12-10_573.jpg]
FileUploadResponse(url=http://127.0.0.1:9000/iron-man/iron-man_1639104331621_2021-12-10_573.jpg, path=http://127.0.0.1:9000/iron-man/iron-man_1639104331621_2021-12-10_573.jpg, newFileName=iron-man_1639104331621_2021-12-10_573.jpg)
获取文件访问外链---------------
http://127.0.0.1:9000/iron-man/iron-man_1639104331621_2021-12-10_573.jpg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=root%2F20211210%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20211210T024531Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=b33040a780c3bd75262ecaa1588d427e80c8b1f1fcbe73ee6da91877c1aa066e
全部桶name---------------
image
image01
iron-man
salt
删除桶---------------
删除文件---------------
image
iron-man
salt