一、MinIO 核心概念
MinIO 是一个高性能的分布式对象存储服务器,兼容 Amazon S3 API,具有以下特点:
高性能:针对存储和检索优化
轻量级:单个二进制文件即可运行
云原生:支持 Kubernetes 部署
S3 兼容:可以直接替换 AWS S3
数据保护:纠删码和加密支持
核心组件
MinIO Server:存储服务主体
MinIO Client (mc):命令行管理工具
MinIO Console:Web 管理界面
二、MinIO 服务端搭建
1. 单机模式部署
使用docker命令拉取镜像
docker pull minio/minio:RELEASE.2023-04-28T18-11-17Z
启动命令
docker run -d \
-p 9000:9000 -p 9001:9001 \
-v ~/minio/data:/data \
--name minio \
docker.io/minio/minio:RELEASE.2023-04-28T18-11-17Z \
server /data --console-address ":9001"
查看启动结果:
在自己的云服务器防火墙上开放9000和9001端口
2. . 访问管理界面
浏览器访问:http://your-server-ip:9001
默认账户密码:
username:minioadmin
password:minioadmin
三、Spring Boot 集成 MinIO
1. 添加依赖
<!-- pom.xml -->
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.5.2</version>
</dependency>
2. 配置 MinIO 客户端
@Configuration
public class MinioConfig {
@Value("${minio.endpoint}")
private String endpoint;
@Value("${minio.accessKey}")
private String accessKey;
@Value("${minio.secretKey}")
private String secretKey;
@Bean
public MinioClient minioClient() {
return MinioClient.builder()
.endpoint(endpoint)
.credentials(accessKey, secretKey)
.build();
}
}
3. 配置文件
# application.yml
minio:
endpoint: http://your-server-ip:9000
accessKey: admin
secretKey: your-strong-password
bucket: images
四、核心功能实现
package com.hl.mybatisplus;
import io.minio.*;
import io.minio.http.Method;
import io.minio.messages.Item;
import org.apache.commons.compress.utils.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.util.List;
import java.util.concurrent.TimeUnit;
@RestController
@RequestMapping("/minio")
public class MinioController {
@Autowired
private MinioClient minioClient;
@Value("${minio.bucket}")
private String bucketName;
// 设置存储桶策略为只读公开
String policy = "{\n" +
" \"Version\": \"2012-10-17\",\n" +
" \"Statement\": [\n" +
" {\n" +
" \"Effect\": \"Allow\",\n" +
" \"Principal\": \"*\",\n" +
" \"Action\": [\"s3:GetObject\"],\n" +
" \"Resource\": [\"arn:aws:s3:::" + bucketName + "/*\"]\n" +
" }\n" +
" ]\n" +
"}";
@RequestMapping("upload")
public String uploadFile(MultipartFile file, String objectName) throws Exception {
// 确保存储桶存在
createBucket();
// 上传文件
ObjectWriteResponse response = minioClient.putObject(
PutObjectArgs.builder()
.bucket(bucketName)
.object(objectName)
.stream(file.getInputStream(), file.getSize(), -1)
.contentType(file.getContentType())
.build());
System.out.println(response);
String url = minioClient.getPresignedObjectUrl(
GetPresignedObjectUrlArgs.builder()
.method(Method.GET)
.bucket(bucketName)
.object(objectName)
.expiry(1, TimeUnit.HOURS)
.build());
System.out.println("Temp URL: " + url);
return objectName;
}
// 控制器示例
@GetMapping("/download/{objectName}")
public void downloadFile(@PathVariable String objectName, HttpServletResponse response) throws Exception {
try (InputStream inputStream = downloadFile(objectName)) {
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition", "attachment; filename=\"" + objectName + "\"");
IOUtils.copy(inputStream, response.getOutputStream());
response.flushBuffer();
}
}
public void createBucket() throws Exception {
boolean found = minioClient.bucketExists(BucketExistsArgs.builder()
.bucket(bucketName)
.build());
if (!found) {
// 设置存储桶策略为只读公开
minioClient.setBucketPolicy(
SetBucketPolicyArgs.builder()
.bucket(bucketName)
.config(policy)
.build());
// minioClient.makeBucket(MakeBucketArgs.builder()
// .bucket(bucketName)
// .build());
}
}
public InputStream downloadFile(String objectName) throws Exception {
return minioClient.getObject(
GetObjectArgs.builder()
.bucket(bucketName)
.object(objectName)
.build());
}
}