一、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;@Beanpublic MinioClient minioClient() {return MinioClient.builder().endpoint(endpoint).credentials(accessKey, secretKey).build();}
}
3. 配置文件
# application.yml
minio:endpoint: http://your-server-ip:9000accessKey: adminsecretKey: your-strong-passwordbucket: 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 {@Autowiredprivate 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());}}