SpringBoot 对象存储 MinIO
1.MinIO简介
MinIO 是一个基于 Go 实现的高性能、兼容 S3 协议的对象存储。它采用 GNU AGPL v3 开源协议,项目地址是 https://github.com/minio/minio,官网是 https://min.io。
它适合存储海量的非结构化的数据,例如说图片、音频、视频等常见文件,备份数据、容器、虚拟机镜像等等,小到 1 KB,大到 5 TB 都可以支持。
国内阿里巴巴、腾讯、百度、华为、中国移动、中国联通等企业在使用 MinIO,甚至不少商业公司二次开发 MinIO 来提供商业化的云存储产品。
疑问:为什么越来越少使用 FastDFS 实现文件存储服务呢?
部署运维复杂、无官方文档、缺乏长期维护的团队、性能较差、未提供 Docker & Kubernetes 集成方案等等原因。
2. MinIO Server 安装
由于 MinIO 是 Go 写的,所以就一个运行程序,因此安装部署 MinIO 就非常简单。
2.1 Linux
## 国外资源,龟速下载
## /usr/local/minio 存储目录;--console-address 是 UI 界面的端口
wget https://dl.min.io/server/minio/release/linux-amd64/minio
chmod +x minio
MINIO_ROOT_USER=admin MINIO_ROOT_PASSWORD=admin123 ./minio server /usr/local/minio --console-address ":9001"
## 国外资源,龟速下载
## /usr/local/minio 存储目录;--console-address 是 UI 界面的端口
wget https://dl.min.io/server/minio/release/linux-amd64/minio
chmod +x minio
MINIO_ROOT_USER=admin MINIO_ROOT_PASSWORD=admin123 ./minio server /usr/local/minio --console-address ":9001"
2.2Docker
Linux 或 MacOS:
cd /usr/local/
mkdir minio
cd /usr/local/
mkdir minio
vi dockercompose.yml
创建dockercompose.yml文件,填写内容如下
version: '3'
services:
minio:
image: minio/minio
container_name: myminio
ports:
- "9001:9000"
volumes:
- /usr/local/minio/data:/data
- /usr/local/minio/config:/root/.minio
environment:
MINIO_ROOT_USER: "admin"
MINIO_ROOT_PASSWORD: "admin123"
command: server /data
restart: always
version: '3'
services:
minio:
image: minio/minio
container_name: myminio
ports:
- "9001:9000"
volumes:
- /usr/local/minio/data:/data
- /usr/local/minio/config:/root/.minio
environment:
MINIO_ROOT_USER: "admin"
MINIO_ROOT_PASSWORD: "admin123"
command: server /data
restart: always
在上面的示例中,
- 我们定义了一个名为
minio
的服务,使用minio/minio
镜像。 - 我们将容器的9000端口映射到主机的9000端口,
具体来说,9001:9000
的格式是 <主机端口>:<容器端口>
。通过这样的端口映射,可以在主机上的 9000 端口访问容器内的服务或应用程序。以便能够通过主机访问MinIO。
- 数据目录
./data
将与容器的/data
目录进行挂载,这样数据可以在容器和主机之间共享。 environment
部分定义了MinIO的环境变量。在这个示例中,我们设置了MINIO_ROOT_USER
和MINIO_ROOT_PASSWORD
来指定MinIO的根用户的用户名和密码。你可以根据需要进行更改。- 最后,
command
部分指定了MinIO容器启动时运行的命令,这里是server /data
,它告诉MinIO在/data
目录下存储数据。
将上述内容保存到名为docker-compose.yml
的文件中,并在该文件所在的目录中运行以下命令启动MinIO容器:
# 后台启动
docker-compose up -d
# docker-compose logs yml里面的服务id # 查看容器输出日志
docker-compose logs minio
# 后台启动
docker-compose up -d
# docker-compose logs yml里面的服务id # 查看容器输出日志
docker-compose logs minio
2.3 访问 UI 界面
使用浏览器访问 http://127.0.0.1:9001 地址,访问 MinIO 内置的 UI 界面。
输入账号 admin,密码 admin123进行登录,成功进入首页。
2.4 新建存储桶
点击 [Create Bucket] 按钮,新建一个 Bucket 存储桶,用于稍后文件的上传。
2.5 添加 readonly 访问规则
默认配置下,访问存储桶是需要请求授权的。但是在实际场景下,我们往往希望允许直接访问,此时就需要添加一条 readonly 访问规则。
① 点击右上角的 [Configure Bucket] 设置图标,然后选择 [Access Rules] 菜单。
2.6 上传文件
点击 [Upload] 按钮,点击 [Upload File] 选项,选择一个图片上传。
2.7 访问文件
文件的访问地址的格式为 <http://127.0.0.1:9000/{bucket}/{name}>
,注意是 9000 端口。
我们刚上传的文件 {bucket}
是 llp,{name}
是 123.png,所以最终的访问路径是 http://127.0.0.1:9000/llp/123.png。
3.Springboot整合minio
3.1引入依赖
<dependencies>
<!-- 实现对 Spring MVC 的自动化配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- MinIO 客户端 -->
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.2.2</version>
</dependency>
</dependencies>
<dependencies>
<!-- 实现对 Spring MVC 的自动化配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- MinIO 客户端 -->
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.2.2</version>
</dependency>
</dependencies>
3.2 Minio配置类
import io.minio.MinioClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MinIOConfiguration {
/**
* Minio 配置
* @return
*/
@Bean
public MinioClient minioClient() {
// 创建 MinioClient 客户端
return MinioClient.builder()
.endpoint(MinioProperties.ENDPOINT)
.credentials(MinioProperties.ACCESS_KEY, MinioProperties.SECRET_KEY)
.build();
}
}
import io.minio.MinioClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MinIOConfiguration {
/**
* Minio 配置
* @return
*/
@Bean
public MinioClient minioClient() {
// 创建 MinioClient 客户端
return MinioClient.builder()
.endpoint(MinioProperties.ENDPOINT)
.credentials(MinioProperties.ACCESS_KEY, MinioProperties.SECRET_KEY)
.build();
}
}
application.yml
minio:
# minio访问地址
endpoint: http://192.168.233.202:9000
# 创建的桶名
bucket: llp
# minio账户名
accessKey: admin
# minio账户密码
secretKey: admin123
spring:
servlet:
# 文件上传相关配置项
multipart:
max-file-size: 16MB # 单个文件大小
max-request-size: 32MB # 设置总上传的文件大小
minio:
# minio访问地址
endpoint: http://192.168.233.202:9000
# 创建的桶名
bucket: llp
# minio账户名
accessKey: admin
# minio账户密码
secretKey: admin123
spring:
servlet:
# 文件上传相关配置项
multipart:
max-file-size: 16MB # 单个文件大小
max-request-size: 32MB # 设置总上传的文件大小
MinioProperties
读取yml配置
import lombok.Data;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Data
@Component
@ConfigurationProperties(value = "minio")
public class MinioProperties implements InitializingBean {
private String endpoint;
private String bucket;
private String accessKey;
private String secretKey;
public static String ENDPOINT;
public static String BUCKET;
public static String ACCESS_KEY;
public static String SECRET_KEY;
@Override
public void afterPropertiesSet() throws Exception {
ENDPOINT = endpoint;
BUCKET = bucket;
SECRET_KEY = secretKey;
ACCESS_KEY = accessKey;
}
}
import lombok.Data;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Data
@Component
@ConfigurationProperties(value = "minio")
public class MinioProperties implements InitializingBean {
private String endpoint;
private String bucket;
private String accessKey;
private String secretKey;
public static String ENDPOINT;
public static String BUCKET;
public static String ACCESS_KEY;
public static String SECRET_KEY;
@Override
public void afterPropertiesSet() throws Exception {
ENDPOINT = endpoint;
BUCKET = bucket;
SECRET_KEY = secretKey;
ACCESS_KEY = accessKey;
}
}
测试类
@RestController
@RequestMapping("/file")
public class FileController {
@Resource
private MinioClient minioClient;
/**
* 上传文件
*/
@PostMapping("/upload")
public String upload(@RequestParam("file") MultipartFile file) throws Exception {
// 上传
String path = UUID.randomUUID().toString(); // 文件名,使用 UUID 随机
minioClient.putObject(PutObjectArgs.builder()
.bucket(MinioProperties.BUCKET) // 存储桶
.object(path) // 文件名
.stream(file.getInputStream(), file.getSize(), -1) // 文件内容
.contentType(file.getContentType()) // 文件类型
.build());
// 拼接路径
return String.format("%s/%s/%s", MinioProperties.ENDPOINT, MinioProperties.BUCKET, path);
}
/**
* 删除文件
*/
@DeleteMapping("/delete")
public String delete(@RequestParam("path") String path) throws Exception {
minioClient.removeObject(RemoveObjectArgs.builder()
.bucket(MinioProperties.BUCKET) // 存储桶
.object(path) // 文件名
.build());
return "success";
}
}
@RestController
@RequestMapping("/file")
public class FileController {
@Resource
private MinioClient minioClient;
/**
* 上传文件
*/
@PostMapping("/upload")
public String upload(@RequestParam("file") MultipartFile file) throws Exception {
// 上传
String path = UUID.randomUUID().toString(); // 文件名,使用 UUID 随机
minioClient.putObject(PutObjectArgs.builder()
.bucket(MinioProperties.BUCKET) // 存储桶
.object(path) // 文件名
.stream(file.getInputStream(), file.getSize(), -1) // 文件内容
.contentType(file.getContentType()) // 文件类型
.build());
// 拼接路径
return String.format("%s/%s/%s", MinioProperties.ENDPOINT, MinioProperties.BUCKET, path);
}
/**
* 删除文件
*/
@DeleteMapping("/delete")
public String delete(@RequestParam("path") String path) throws Exception {
minioClient.removeObject(RemoveObjectArgs.builder()
.bucket(MinioProperties.BUCKET) // 存储桶
.object(path) // 文件名
.build());
return "success";
}
}
4.测试
文件上传测试
上传成功后,我们获得了文件的访问 URL 地址,可以使用浏览器直接访问。
http://192.168.233.202:9000/llp/8028e9c9-8b22-4a57-bcdc-74eb96a585da
同时在minio后台也可以看到上传的文件
文件删除测试