MinIO文件服务器
前言
这个MinIO服务用起来比较简单,配置和使用都非常快。
1.博客案例源码
git clone https://github.com/YeZhiyue/MinIO-Server.git
2. 官方文档
服务器部署
docker run -p 9000:9000 --name minio1 \
-e "MINIO_ACCESS_KEY=AKIAIOSFODNN7EXAMPLE" \
-e "MINIO_SECRET_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY" \
-v /mnt/data:/data \
-v /mnt/config:/root/.minio \
minio/minio server /data
依赖配置
<!-- 文件服务器MinIO -->
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>6.0.8</version>
</dependency>
# ============== MinIO =================
minio:
endpoint: http://localhost:9000
access-key: AKIAIOSFODNN7EXAMPLE
secret-key: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
bucket: common
transfer-protocol: http
SpringBoot配置
方法模板类
用来抽取MinIO中常用的操作
@Configuration
@Data
@NoArgsConstructor
@ConfigurationProperties(prefix = "minio")
public class MinioTemplate {
// 终端,也就是MinIO服务器的地址
private String endpoint;
// 密钥
private String accessKey;
private String secretKey;
// 请求协议
private String transferProtocol;
// 核心,和服务器交互的主要类
private MinioClient client;
/**
* @description 注册MinioClient
* @author 叶之越
* @email 739153436@qq.com
* @date 2020/10/2 15:55
*/
@Bean
public MinioClient getMinioClient() throws Exception {
this.client = new MinioClient(endpoint, accessKey, secretKey);
return this.client;
}
/**
* 创建bucket,等价于我们在电脑上创建一个目录
*/
@SneakyThrows
public void createBucket(String bucketName) {
if (!client.bucketExists(bucketName)) {
client.makeBucket(bucketName);
}
}
/**
* 获取全部bucket
*/
@SneakyThrows
public List<Bucket> getAllBuckets() {
return client.listBuckets();
}
@SneakyThrows
public Optional<Bucket> getBucket(String bucketName) {
return client.listBuckets().stream().filter(b -> b.name().equals(bucketName)).findFirst();
}
/**
* 移除桶
*/
@SneakyThrows
public void removeBucket(String bucketName) {
client.removeBucket(bucketName);
}
/**
* 根据文件前置查询文件
*
* @param bucketName bucket名称
* @param prefix 前缀
* @param recursive 是否递归查询
* @return Item 列表
*/
@SneakyThrows
public List<Item> getAllObjectsByPrefix(String bucketName, String prefix, boolean recursive) {
List<Item> fileInfoList = new ArrayList<>();
for (Result<Item> itemResult : client
.listObjects(bucketName, prefix, recursive)) {
fileInfoList.add(itemResult.get());
}
return fileInfoList;
}
/**
* 获取文件外链
*
* @param bucketName bucket名称
* @param objectName 文件名称
* @param expires 过期时间 <=7
* @return url
*/
@SneakyThrows
public String getObjectURL(String bucketName, String objectName, Integer expires) {
return client.presignedGetObject(bucketName, objectName, expires);
}
/**
* 获取文件
*
* @param bucketName bucket名称
* @param objectName 文件名称
* @return 二进制流
*/
@SneakyThrows
public InputStream getObject(String bucketName, String objectName) {
return client.getObject(bucketName, objectName);
}
/**
* 上传文件,"application/octet-stream"表示直接以二进制的形式上传图片,这样子会导致我们在下载MinIO资源的时候是直接以二进制的形式直接下载,而不是直接展示
*
* @param bucketName bucket名称
* @param objectName 文件名称
* @param stream 文件流
*/
public void putObject(String bucketName, String objectName, InputStream stream) throws Exception {
client.putObject(bucketName, objectName, stream, (long) stream.available(), null, null, "application/octet-stream");
}
/**
* 上传文件
*
* @param bucketName bucket名称
* @param objectName 文件名称
* @param stream 文件流
* @param contentType 表示以什么MiMe类型进行文件的上传
*/
public void putObject(String bucketName, String objectName, InputStream stream, String contentType) throws Exception {
client.putObject(bucketName, objectName, stream, (long) stream.available(), null, null, contentType);
}
/**
* 上传文件
*
* @param bucketName bucket名称
* @param objectName 文件名称
* @param stream 文件流
* @param size 大小
* @param contextType 类型
*/
public void putObject(String bucketName, String objectName, InputStream stream, long size, String contextType) throws Exception {
client.putObject(bucketName, objectName, stream, size, null, null, contextType);
}
/**
* 获取文件信息
*
* @param bucketName bucket名称
* @param objectName 文件名称
*/
public ObjectStat getObjectInfo(String bucketName, String objectName) throws Exception {
return client.statObject(bucketName, objectName);
}
/**
* 删除文件
*
* @param bucketName bucket名称
* @param objectName 文件名称
*/
public void removeObject(String bucketName, String objectName) throws Exception {
client.removeObject(bucketName, objectName);
}
}
方法使用示例
1.1 文件上传
minioTemplate.putObject(DEFAULT_BUCKET_NAME, fileName, multipartFile.getInputStream(),contentType);
1.2 文件删除
minioTemplate.removeObject(DEFAULT_BUCKET_NAME, minioResource.getFileName());
易错点和注意点
MinIO的文件上传时文件类型设置的坑
踩坑一:如果你不设置类型,MinIO是默认以 application/octet-stream (二进制流数据)的形式上传,那么你在使用文件链接去访问这个图片你的时候就会直接下载这个图片而不是展示这张图片。
解决方案:根据文件名来获取文件的MIME类型然后上传文件
String contentType = new MimetypesFileTypeMap().getContentType(originalFilename);
// 示例;image/jpeg
minioTemplate.putObject(DEFAULT_BUCKET_NAME, fileName, multipartFile.getInputStream(), contentType);
踩坑二:如果你不对桶的权限进行设置,那么你就只能通过获取外链来访问,而且MinIO的外链都是有期限的(最大不超过7天)
外链示例:http://59.110.213.92:9000/common/1311962372995112962.jpg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIOSFODNN7EXAMPLE%2F20201002%2F%2Fs3%2Faws4_request&X-Amz-Date=20201002T105151Z&X-Amz-Expires=432000&X-Amz-SignedHeaders=host&X-Amz-Signature=cbdf8590b74ea668eabf0cba0cc9b7bdfadf01a099fb377f213fd29d63dbf31c
解决方案:所以如果你想要不通过外链来访问文件,那么就需要对桶进行策略设置,就是设置访问权限,可以自定义Url过滤规则
直链示例(经过下面的配置就可以不用通过外链才能访问到文件了):http://59.110.213.92:9000/common/1311962372995112962.jpg