一、Minio介绍:
目前可用于文件存储的网络服务选择也有不少,比如阿里云OSS、七牛云、腾讯云等等,可是收费都有点小贵。为了省钱,很多公司使用MinIO做为文件服务器。
官网:https://www.minio.org.cn/
MinIO是一个开源的分布式对象存储服务器,支持S3协议并且可以在多节点上实现数据的高可用和容错。它采用Go语言开发,拥有轻量级、高性能、易部署等特点,并且可以自由选择底层存储介质。它基于Apache License 开源协议,兼容Amazon S3云存储接口。适合存储非结构化数据,如图片,音频,视频,日志等。
二、使用spring boot整合Minio,完成文件的上传、下载和删除。
版本:spring boot3、jdk17、Minio的版本为:RELEASE.2023-11-01T18-37-25Z
本次使用knife4j进行测试;
创建一个空的spring boot项目,并引入如下依赖:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
<version>4.3.0</version>
</dependency>
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.5.2</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
在yml配置文件中引入如下配置:
minio:
url: http://192.168.231.110:9001
username: admin
password: admin123456
bucketName: test
spring:
servlet:
multipart:
max-file-size: 10MB # 单个文件上传的最大上限
max-request-size: 100MB # 整个请求体的最大上限
minio:我们自定义的属性
url:你的服务端地址
username:用户名
password:密码
bucketName:test(桶的名称,我们现在没有创建,一会用Java代码实现)
max-file-size:一定要配置这个属性,不然springboot默认的单个文件上传的最大上限为1MB,超过这个上限,就会报错。
1、创建一个实体类来继承yml文件中minio的连接信息;
@ConfigurationProperties(prefix = "minio")
@Component
@Data
public class MinioPojo {
private String url;
private String username;
private String password;
private String bucketName;
}
2、自定义bean,将MinioClient初始化;
@Configuration
public class MinioConfig {
@Autowired
private MinioPojo minioPojo;
@Bean
public MinioClient minioClient(){
return MinioClient.builder()
.endpoint(minioPojo.getUrl()) //传入url地址
//传入用户名和密码
.credentials(minioPojo.getUsername(), minioPojo.getPassword())
.build(); //完成MinioClient的初始化
}
}
3、新创建一个MinioService类,用来进行文件的操作,并注册为bean。将来在这里进行具体代码的编写。
@Component
public class MinioService {
@Autowired
private MinioClient minioClient;
@Autowired
private MinioPojo minioPojo;
}
4、新建一个Controller,用来进行文件的上传。
@RestController
@RequestMapping("/tests")
public class TestController {
@Autowired
private MinioService minioService;
@Autowired
private MinioPojo minioPojo;
//文件上传
@Operation(summary = "上传图片")
@PostMapping("/uploadImage")
public String aa(MultipartFile file){
String url = minioService.uploadImage(minioPojo.getBucketName(), file);
return url;
}
}
我们在MinioService中定义了uploadImage方法,传入了两个参数。一个是桶的名称,一个是文件file。(注意参数名称一定要叫file,因为现在前端默认传文件时都会叫这个名字,如果你随意的更改名字,后端会接收不到参数。)
返回文件在Minio中的地址url。(注意,只要你的容器Minio还在运行,就可以直接访问到。)
5、在MinioService中进行方法的实现。
@Autowired
private MinioClient minioClient;
@Autowired
private MinioProperties minioProperties;
/*
* 上传文件
* */
public String uploadFile(MultipartFile file) {
try {
//判断桶是否存在
boolean bucketExists = minioClient.bucketExists(BucketExistsArgs.builder().bucket(minioProperties.getBucketName()).build());
if (!bucketExists){
// 如果不存在,就创建桶
minioClient.makeBucket(MakeBucketArgs.builder().bucket(minioProperties.getBucketName()).build());
}
// 本地时间,具体到年、月、日
String yyyymmdd = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
// String uuid= UUID.randomUUID().toString();
String filename = yyyymmdd+"/"+file.getOriginalFilename();
// 加一个/表示创建一个文件夹
minioClient.putObject(PutObjectArgs.builder().
bucket(minioProperties.getBucketName()).
object(filename).
stream(file.getInputStream(), file.getSize(), -1).
// 文件上传的类型,如果不指定,那么每次访问时都要先下载文件
contentType(file.getContentType()).
build());
String url= minioProperties.getUrl()+"/"+ minioProperties.getBucketName()+"/"+filename;
return url;
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("文件上传失败");
}
}