课堂目标
- 了解什么是Minio
- 下载与安装
- SpringBoot集成
Minio使用
一、Minio是什么?

1.1 Minio 介绍(文件存储服务器)
https://minio.org.cn
MinIO 是一个基于 Apache License v2.0 开源协议的对象存储服务。它兼容亚马逊 AWS S3 云存储服务接口,非常适合于存储大容量非结构化的数据,例如图片、视频、日志文件、备份数据和容器 / 虚拟机镜像等,而一个对象文件可以是任意大小,从几 kb 到最大 5T 不等。
MinIO 是一个非常轻量的服务,可以很简单的和其他应用的结合,类似 NodeJS, Redis 或者 MySQL。
AWS S3(Amazon Simple Storage Service)本身是一项对象存储服务,而它定义的API接口规范,已成为业界事实标准
概念:S3协议本质上是一套基于HTTP/HTTPS的RESTful API接口规范,定义了如何通过HTTP请求来操作云端数据。
S3 的核心概念
- Bucket(存储桶):对象的容器,全局唯一。存储文件对象的目录。
- Object(对象):存储的基本数据单元,由数据、Key(键) 和元数据组成。Key是对象的唯一标识。
- Endpoint(访问端点):服务的访问地址;URL (c://data/file....)
二、minio安装
1、docker安装(可选)
https://minio.org.cn/solutions/modern-data-lakes-lakehouses.html
- docker下载mimio
docker pull minio/minio
- 在/data目录下创建minio的配置文件和数据文件,方便把容器内部的文件映射到宿主机
cd /data
mkdir -p minio/config
mkdir -p minio/data
- 拉起镜像
docker run \ #运行或者叫拉起
--name minio \ #别名
-p 9000:9000 \ #映射端口 ,前面是宿主机 后面是容器内部
-p 9090:9090 \
-d \ #后台启动
-e "MINIO_ROOT_USER=minio" \ # 设置一个环境变量值 用户名
-e "MINIO_ROOT_PASSWORD=minio123" \ # 密码
-v /data/minio/data:/data \ #映射 把容器的 /data目录 映射到 宿主机的/data/minio/data
-v /data/minio/config:/root/.minio \ #配置映射
minio/minio server /data --console-address ":9090" --address ":9000"
#minio/minio minio的命令 server 服务启动 /data指定文件存放的目录 --consol-address代表web界面的端口 --addresss 9000 代表是上传的端口
docker run \
--name minio \
-p 9000:9000 \
-p 9090:9090 \
-d \
-e "MINIO_ROOT_USER=minio" \
-e "MINIO_ROOT_PASSWORD=minio123" \
-v /data/minio/data:/data \
-v /data/minio/config:/root/.minio \
minio/minio server /data --console-address ":9090" --address ":9000"
docker run --name minio -p 9000:9000 -p 9090:9090 -d -e "MINIO_ROOT_USER=minio" -e "MINIO_ROOT_PASSWORD=minio123" -v /data/minio/data:/data -v /data/minio/config:/root/.minio minio/minio server /data --console-address ":9090" --address ":9000"
2、windows安装(必会)
- 下载

-
配置目录+密码
如果不在环境变量里面配置密码,会给一个默认的密码; 在环境变量里面配置参数(用户名和密码),是为了安全性,密码不会被轻易看到,一般只有拿到找个主机权限的人才会知道密码 PS> set MINIO_ROOT_USER=admin PS> set MINIO_ROOT_PASSWORD=minioadmin123 PS> C:\minio.exe server F:\Data --console-address ":9001" //启动1、自己创建一个目录data
2、设置环境变量密码
3、minio.exe就是启动文件服务的执行文件,后面的server代表提供文件服务 ,后面的是存放的目录,--console代表启动的端口

访问控制台
三、控制台看一下
- 登录
http://localhost:9001/login
minio
minio123

- 新建一个bucket,必须要有





四、springboot如何使用
- 加依赖
<!--minio-->
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.5.10</version>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
</dependency>
<!-- 工具包 util -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.3.10</version>
</dependency>
- 配置、
minio:
access-key: minio
secret-key: minio123
endpoint: http://47.109.102.26:9000
bucket: woniu
- 配置类
package com.dw.config;
import io.minio.MinioClient;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@ConfigurationProperties(prefix = "minio")
@Data
public class MinioConfig {
private String endpoint;
private String accessKey;
private String secretKey;
private String bucket;
@Bean
public MinioClient minioClient() {
return MinioClient.builder()
.endpoint(endpoint)
.credentials(accessKey, secretKey)
.build();
}
}
- 编写service
package com.dw.service;
import io.minio.errors.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
/**
* @author daiwei
* @date 2025/10/16/19:33
* @Description:
*/
public interface MinioService {
String uploadFile(MultipartFile file) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException;
String getFileUrl(String fileName, int expires);
}
- 编写service实现
package com.dw.service.impl;
import cn.hutool.core.date.DateUtil;
import com.dw.config.MinioConfig;
import com.dw.service.MinioService;
import io.minio.*;
import io.minio.errors.*;
import io.minio.http.Method;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
/**
* @author daiwei
* @date 2025/10/16/19:33
* @Description:
*/
@Service
public class MinioServiceImpl implements MinioService {
@Autowired
MinioConfig minioConfig;
public String uploadFile(MultipartFile file) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
// 1. 检查存储桶是否存在,不存在则创建
if (!minioClient.bucketExists(BucketExistsArgs.builder().bucket(minioConfig.getBucket()).build())) {
minioClient.makeBucket(MakeBucketArgs.builder().bucket(minioConfig.getBucket()).build());
}
// 2. 生成唯一文件名
String originalFilename = file.getOriginalFilename(); // example.txt
String fileExtension = originalFilename.substring(originalFilename.lastIndexOf(".")); // .txt
String objectName = DateUtil.today().replace("-", "")+"/"+ UUID.randomUUID().toString() + fileExtension; // 随机字符串 + .txt
// 3. 上传文件
minioClient.putObject(
PutObjectArgs.builder()
.bucket(minioConfig.getBucket()) // 存储桶名称
.object(objectName) // 对象名称(文件名,可以包含目录,test/随机字符串.txt)
.stream(file.getInputStream(), file.getSize(), -1) // 文件流,文件大小,每次读取
.contentType(file.getContentType()) // 文件类型,比如 image/jpeg
.build());
return objectName;
}
/**
* @param objectFile 对象文件
* @return {@link String }
* @Description 根据文件名和桶获取文件路径
*/
@Override
public String getFileUrl(String objectFile,int expires) {
try {
return minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
.method(Method.GET)
.bucket(minioConfig.getBucket())
.object(DateUtil.today().replace("-", "")+"/"+objectFile)
.expiry(expires, TimeUnit.SECONDS)
.build()
);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
- controller
package com.dw.controller;
import com.dw.service.MinioService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.util.Arrays;
import java.util.List;
/**
* @author daiwei
* @date 2025/10/16/19:56
* @Description:
*/
@RestController
@RequestMapping("/minio")
public class MinioController{
// 最大文件大小(10MB)
private static final long MAX_FILE_SIZE = 10 * 1024 * 1024;
// 允许的文件类型
private static final List<String> ALLOWED_EXTENSIONS = Arrays.asList(
".jpg", ".jpeg", ".png", ".gif", ".pdf", ".doc", ".docx", ".txt"
);
@Autowired
MinioService orderService;
@PostMapping("/upload")
public String upload(@RequestParam("file") MultipartFile file) throws Exception {
if(file.getSize()>MAX_FILE_SIZE){
throw new IllegalAccessException("文件过大");
}
String ext = file.getOriginalFilename().substring( file.getOriginalFilename().lastIndexOf("."));
if (!ALLOWED_EXTENSIONS.contains(ext)) {
throw new IllegalArgumentException("不支持的文件类型,仅支持: " + ALLOWED_EXTENSIONS);
}
return orderService.uploadFile(file);
}
@GetMapping("/getUrl")
public String getFileUrl(@RequestParam("filename") String fileName){
return orderService.getFileUrl(fileName, 30);
}
}
五、还有哪些API


六、其他介绍(可选)
官网api demo
https://github.com/minio/minio-java/blob/release/examples/UploadObject.java
- 分片上传
把一个大文件,拆分成n个小文件,逐一上传;
上传完毕,后把N个文件最终合并成一个整体文件。
分片:
1、随时可以暂停,更灵活
2、断点续传
3、多线程去上传

-
秒传(闪传)
用hash或者是md5 标志唯一的指纹,在下一次上传的时候,再次用同样的hash或者md5去验证是否一样
如果是一样就代表已经被上传过,只需要做对应的md5值关联文件对象即可。

26-3阶内容-2.3.1-Minio
https://xiaochenblog.icu/archives/26-3jie-nei-rong-2.3.1-minio
评论