Java使用MinIO实现文件上传功能
MinIO介绍
什么是MinIO
Minio 是个基于 Golang 编写的开源对象存储套件,基于Apache License v2.0开源协议,虽然轻量,却拥有着不错的性能。它兼容亚马逊S3云存储服务接口。可以很简单的和其他应用结合使用,例如 NodeJS、Redis、MySQL等。
应用场景
可以作为私有云的对象存储服务来使用,也可以作为云对象存储的网关层,无缝对接 Amazon S3
或者 MicroSoft Azure
。
特点
-
高性能:作为一款高性能存储,在标准硬件条件下,其读写速率分别可以达到 55Gb/s 和 35Gb/s。并而 MinIO 支持一个对象文件可以是任意大小,从几kb到最大5T不等。
-
可扩展:不同MinIO集群可以组成联邦,并形成一个全局的命名空间,并跨越多个数据中心
-
云原生:容器化、基于K8S的编排、多租户支持
-
Amazon S3兼容:Minio使用Amazon S3 v2 / v4 API。可以使用Minio SDK,Minio Client,AWS SDK和AWS CLI访问Minio服务器。
-
可对接后端存储: 除了Minio自己的文件系统,还支持DAS、 JBODs、NAS、Google云存储和Azure Blob存储。
-
SDK支持: 基于Minio轻量的特点,它得到类似Java、Python或Go等语言的sdk支持
-
JavaSDK: https://github.com/minio/minio-java
-
PythonSDK: https://github.com/minio/minio-py
-
Lambda计算: Minio服务器通过其兼容AWS SNS / SQS的事件通知服务触发Lambda功能。支持的目标是消息队列,如Kafka,NATS,AMQP,MQTT,Webhooks以及Elasticsearch,Redis,Postgres和MySQL等数据库。
-
有操作页面
-
功能简单: 这一设计原则让MinIO不容易出错、更快启动
-
支持纠删码:MinIO使用纠删码、Checksum来防止硬件错误和静默数据污染。在最高冗余度配置下,即使丢失1/2的磁盘也能恢复数据
安装
docker 安装
下载镜像
docker pull minio/minio
启动容器
docker run -d \
-p 9000:9000 \
-p 9001:9001 \
--name minio \
-v /mnt/data:/data \
-e "MINIO_ROOT_USER=minioadmin" \
-e "MINIO_ROOT_PASSWORD=minioadmin" \
minio/minio \
server /data --console-address ":9001"
参数解释
# 命令详解
# -e MINIO_ROOT_USER 指定用户名
# -e MINIO_ROOT_PASSWORD 指定密码
# -v 挂载目录,持久化minio目录
配置
使用 docker命令中的账号密码登录http://127.0.0.1:9001/login,本例中用户名:minioadmin, 密码:minioadmin。
image.png创建bucket
image.png
输入bucket name
image.png
配置权限
image.png image.png
创建access key
image.png image.png
记录下access key, secret key 留作后面使用
JAVA 使用
基于spring boot对接minio的文件上传功能
引入MinIO
pom引入依赖
这里有个坑,记住版本选择8.2.1 高版本的会有问题,运行时报错。
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.2.1</version>
</dependency>
增加minio配置
application.yml
spring:
servlet:
multipart:
max-file-size: 10MB # 文件上传大小限制
minio:
url: http://127.0.0.1:9000 # 内网上传的链接
bucket: mytest # bucket name
readUrl: http://127.0.0.1:9000 # 外网访问的链接
accessKey: xxxxxxxxxxxx # 上一步的access key
secretKey: xxxxxxxxxxxxxxxxxxx # 上一步的secret key
创建MinioClient Bean
@Configuration
public class MinioConfig {
@Value("${minio.url}")
private String url;
@Value("${minio.accessKey}")
private String accessKey;
@Value("${minio.secretKey}")
private String secretKey;
@Bean
public MinioClient getMinioClient() {
return MinioClient.builder().endpoint(url)
.credentials(accessKey, secretKey).build();
}
}
上传接口实现
实现上传服务方法
先定义一个文件服务接口,以后如果有更好的实现方式,增加实现即可
public interface FileService {
String upload(MultipartFile file) throws Exception;
}
minio的实现
@Service
public class MinioFileServiceImpl implements FileService {
@Value("${minio.bucket}")
private String bucket;
@Value("${minio.readUrl}")
private String readUrl;
@Resource
private MinioClient minioClient;
@Override
public String upload(MultipartFile file) throws Exception{
String filename = getFileName(file.getOriginalFilename());
ObjectWriteResponse res = minioClient.putObject(PutObjectArgs.builder()
.bucket(bucket)
.object(filename)
.contentType(file.getContentType())
.stream(file.getInputStream(), file.getSize(), ObjectWriteArgs.MIN_MULTIPART_SIZE).build());
// 返回可访问的图片链接
return readUrl + "/" + bucket + "/" + filename;
}
private String getFileName(String filename){
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
// 设置存储对象名称
String dir = sdf.format(new Date());
int idx = filename.lastIndexOf(".");
if (idx >= 0) {
String ext = filename.substring(idx+1);
String name = System.currentTimeMillis() + filename.substring(0, idx);
filename = XString.md5(name) + "." + ext;
}
return dir + "/" +filename;
}
}
controller
@Controller
@RequestMapping("/minio")
public class MinioController {
private static final Logger LOGGER = LoggerFactory.getLogger(MinioController.class);
@Resource(type = MinioFileServiceImpl.class)
private FileService fileService;
@RequestMapping(value = "/upload", method = RequestMethod.POST)
@ResponseBody
public CommonResult upload(@RequestPart("file") MultipartFile file) {
try {
return CommonResult.success(fileService.upload(file));
} catch (Exception e) {
LOGGER.error("upload file exception {}", e.getMessage(), e);
return CommonResult.failed(ResultCode.FAILED);
}
}
}
测试
启动服务,使用postman测试
postman配置
请求头设置
Content-Type:multipart/form-data
image.png查看minio上传的文件
image.png至此,完成文件上传功能。
最后附上源码:https://github.com/chain-zhang/study
欢迎大家指正。