Spring Boot 3 整合 minio 实现文件存储
01、背景介绍
在软件系统的实际开发进程里,文件存储服务的使用常常是难以避免的。
就拿小型网站系统来说,一般情况下,会把文件存储服务和网站系统部署在同一台服务器上。这种做法在小成本资源投入方面确实具有一定优势。如果网站的访问量处于较低水平,这种方式基本不会引发什么问题。然而,随着网站访问量的逐步攀升,网站文件资源的读取操作变得越来越频繁。此时,单台服务器可能就无法承受如此大量的请求了,进而导致网站打不开或者出现系统异常等情况。
MinIO,作为一款被宣称是世界上速度最快的对象存储服务器,主要为大规模的数据存储和分析而精心打造。它具有很强的适应性,能够在多种环境下进行部署,像物理服务器、虚拟机、容器等都不在话下。更为重要的是,MinIO的技术文档十分完备,这就意味着使用者可以轻松上手。而且,对于个人用户而言,它完全是开源免费的。
今天这篇文章就将带大家一同探索如何运用MinIO搭建一套专属的云存储服务。
2、方案实践
2.1、minio 快速安装
以 windows 操作系统为例,安装请参考《Windows下Minio的安装以及基本使用》。
2.2.3、设置文件公开访问
默认创建的存储桶,都是私有桶,也就是说无法被公开访问。
3、springBoot 集成 minio 实现文件存储
我们一起来看看,如何在 Spring Boot 工程中集成 minio 客户端以便实现文件存储服务。
3.1、创建用户访问密钥
MinIO 支持通过用户、密码来管理存储桶,我们可以利用 minio 客户端来实现文件的上传和下载。点击Access Keys菜单,创建用户名和密码并将其保存,下文会用到。
3.2、引入依赖包
在 Spring Boot 工程,引入 minio 客户端依赖包。我们可以去官网看找到最新的依赖。
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.5.10</version>
</dependency>
3.3、添加相关配置
在application.properties文件中,添加 minio 相关的配置信息.
minio.endpoint=http://127.0.0.1:9090
# 使用账号密码
#minio.access-key=minioadmin
#minio.secret-key=password
# 使用密钥
minio.access-key=eFbF9rSBtgfqiLGDcPDo
minio.secret-key=Sfgc06T1S6zhzVTzCwIFhr6KUs7zqCwOwFkHHez4
minio.bucket-name=harry
API: http://127.0.0.1:9090RootUser: minioadminRootPass: password
注意下这里,因为我们配置的端口是
9090
,所以这里是9090
而不是9000
,要不会出现io.minio.errors.InvalidResponseException: Non-XML response from server. Response code: 400, Content-Type: text/xml;......
异常信息
3.4、编写 Minio 客户端配置类
基于上文的配置信息,编写 Minio 客户端配置类。
@Configuration
public class MinioConfig {
@Value("${minio.endpoint}")
private String minioEndpoint;
@Value("${minio.access-key}")
private String minioAccessKey;
@Value("${minio.secret-key}")
private String minioSecretKey;
@Bean
public MinioClient minioClient() {
return MinioClient.builder()
.endpoint(minioEndpoint)
.credentials(minioAccessKey, minioSecretKey)
.build();
}
}
3.5、编写上传和文件预览服务
接着利用 minioClient 客户端,编写上传和文件预览服务。
/**
* @author harry
* @公众号 Harry技术
*/
@RestController
public class FileController {
@Value("${minio.bucket-name}")
private String bucketName;
@Autowired
private MinioClient minioClient;
/**
* 文件上传
*/
@PostMapping("/upload")
public String upload(@RequestParam("file") MultipartFile file) {
// 生成文件名(日期文件夹)
String suffix = FileUtil.getSuffix(file.getOriginalFilename());
String uuid = IdUtil.simpleUUID();
String fileName = DateUtil.format(LocalDateTime.now(), "yyyyMMdd") + "/" + uuid + "." + suffix;
// try-with-resource 语法糖自动释放流
try (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;
GetPresignedObjectUrlArgs getPresignedObjectUrlArgs = GetPresignedObjectUrlArgs.builder()
.bucket(bucketName).object(fileName)
.method(Method.GET)
.build();
fileUrl = minioClient.getPresignedObjectUrl(getPresignedObjectUrlArgs);
fileUrl = fileUrl.substring(0, fileUrl.indexOf("?"));
return fileUrl;
} catch (Exception e) {
e.printStackTrace();
return e.getMessage();
}
}
}
3.6、使用Apifox上传
返回图片地址:http://127.0.0.1:9090/harry/20250109/0fd3f0df56674ede8be935951d3170cf.png
curl --location --request POST 'http://127.0.0.1:8080/upload' \
--header 'User-Agent: Apifox/1.0.0 (https://apifox.com)' \
--header 'Accept: /' \
--header 'Host: 127.0.0.1:8080' \
--header 'Connection: keep-alive' \
--header 'Content-Type: multipart/form-data; boundary=--------------------------602606623533285111744711' \
--form 'file=@"C:\Users\Admin\Downloads\微信截图_20250106132845.png"'
3.7、验证
回到 minio 控制台,可以看到刚刚上传的文件信息。
2)文件预览地址验证
在浏览器端,访问http://127.0.0.1:9090/harry/20250109/0fd3f0df56674ede8be935951d3170cf.png
预览地址,可以清晰的看到图片能正常展示。
总结
到这里,我们已经掌握了springBoot 整合 minio 实现文件存储的过程。
示例源码:关注公众号“Harry技术”,回复 minio 获取源码地址。