简介
Minio是一个高性能、开源的 S3 兼容对象存储系统,采用 Go 语言编写,支持分布式部署。具有如下特点:
1、支持离线部署,可在本地 NAS 或服务器上运行;
2、提供 Web 控制台,管理存储桶和访问密钥;
3、兼容 AWS S3 API,便于集成现有应用;
官方文档:minio documentation
Docker部署
1、拉取minio镜像
docker search minio docker pull minio/minio
2、创建容器
#创建需要挂载的文件夹 mkdir -p /root/home/minio/data mkdir -p /root/home/minio/config docker run -p 9010:9000 -p 9011:9001 --name minio \ --restart=always \ --privileged=true \ -v /root/home/minio/data:/data \ -v /root/home/minio/config:/root/.minio \ -e "MINIO_ACCESS_KEY=minioImooc" \ -e "MINIO_SECRET_KEY=www.imooc.com" \ -e "MINIO_CONSOLE_ADDRESS=:9001" \ -d quay.io/minio/minio:RELEASE.2025-04-08T15-41-24Z server /data \ --console-address ":9001"
命令解释
-p 9010:9000 #API端口,因为服务器9000端口被占用了,所以改成9010端口了 -p 9011:9001 #控制台端口 --restart=always #重启策略,开机自动启动,不需要可以删掉 --privileged=true #权限 -e "MINIO_ACCESS_KEY=minioImooc" #access key,类似于登录账户 -e "MINIO_SECRET_KEY=www.imooc.com" #secret key,类似于登录密码 -e "MINIO_CONSOLE_ADDRESS=:9001" #指定控制台端口
创建成功后需开放9010和9011端口。
sudo firewall-cmd --zone=public --add-port=9010/tcp --permanent sudo firewall-cmd --zone=public --add-port=9011/tcp --permanent sudo firewall-cmd --reload
访问地址:http://ip:9011。
创建一个公开的bucket
1、创建一个bucket
首先登录minio控制台,账户密码就是刚才配置的access_key和secret_key。路径:Buckets->Create Bucket。
2、访问策略设为公开。如果不设置公开,则无法拿到长期有效的文件访问连接。
3、创建access key,用于api调用
Spring 集成minio
1、添加依赖
pom.xml
<!-- MinIO Java SDK --> <dependency> <groupId>io.minio</groupId> <artifactId>minio</artifactId> <version>8.5.7</version> </dependency>
2、配置Minio信息
application.yaml
minio: endpoint: http://ip:port access-key: your_access_value secret-key: your_secret_value bucket-name: your_bucket_name
3、创建Minio配置类
import lombok.Getter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Getter
@Component
public class MinioOptions
{
@Value("${minio.endpoint}")
private String endpoint;
@Value("${minio.access-key}")
private String accessKey;
@Value("${minio.secret-key}")
private String secretKey;
@Value("${minio.bucket-name}")
private String bucketName;
}import io.minio.MinioClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MinioConfig
{
private final MinioOptions minioOptions;
public MinioConfig(MinioOptions minioOptions) {
this.minioOptions = minioOptions;
}
@Bean
public MinioClient minioClient(){
return MinioClient.builder()
.endpoint(minioOptions.getEndpoint())
.credentials(minioOptions.getAccessKey(), minioOptions.getSecretKey())
.build();
}
} 4、创建Minio service类
import io.minio.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.IOUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import java.io.InputStream;
import java.util.Base64;
@Slf4j
@Service
@RequiredArgsConstructor
public class MinioService
{
private final MinioClient minioClient;
private final MinioOptions minioOptions;
//上传图片
public String uploadImage(MultipartFile file,String objectName)
{
try {
//检查bucket是否存在,不存在则创建
boolean found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(minioOptions.getBucketName()).build());
if (!found) {
minioClient.makeBucket(MakeBucketArgs.builder().bucket(minioOptions.getBucketName()).build());
}
//上传图片
minioClient.putObject(
PutObjectArgs.builder()
.bucket(minioOptions.getBucketName())
.object(objectName)
.stream(file.getInputStream(),file.getSize(),-1)
.contentType(file.getContentType())
.build());
//获取图片url
return String.format("%s/%s/%s",
minioOptions.getEndpoint(),
minioOptions.getBucketName(),
objectName);
} catch (Exception e){
log.error("上传图片失败:{}",e.getMessage());
throw new RuntimeException("上传图片失败",e);
}
}
public void deleteImageByUrl(String imageUrl)
{
String objectName = getObjectName(imageUrl);
deleteImage(objectName);
}
//删除图片
public void deleteImage(String objectName)
{
try {
minioClient.removeObject(
RemoveObjectArgs.builder()
.bucket(minioOptions.getBucketName())
.object(objectName)
.build());
} catch (Exception e){
log.error("删除图片失败:{}",e.getMessage());
throw new RuntimeException("删除图片失败",e);
}
}
public String getImageAsBase64ByUrl(String imageUrl)
{
String objectName = getObjectName(imageUrl);
return getImageAsBase64(objectName);
}
//图片转Base64
public String getImageAsBase64(String objectName)
{
try (InputStream stream = minioClient.getObject(
GetObjectArgs.builder()
.bucket(minioOptions.getBucketName())
.object(objectName)
.build())) {
byte[] bytes = IOUtils.toByteArray(stream);
return Base64.getEncoder().encodeToString(bytes);
} catch (Exception e) {
log.error("获取图片Base64失败: {}", e.getMessage());
throw new RuntimeException("获取图片Base64失败", e);
}
}
public String getObjectName(String imageUrl)
{
if (!StringUtils.hasText(imageUrl)) {
return "";
}
// 找到最后一个"/"的位置
int lastSlashIndex = imageUrl.lastIndexOf('/');
if (lastSlashIndex == -1) {
return "";
}
return imageUrl.substring(lastSlashIndex + 1);
}
} 5、创建控制器
import io.swagger.v3.oas.annotations.Operation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import withub.framework.utils.StringTool;
import withub.gs.application.externalService.minio.MinioService;
import withub.gs.contract.param.staff.FaceUploadParam;
import withub.gs.contract.param.staff.FileDelParam;
import java.util.Objects;
@Slf4j
@RestController
@RequestMapping(ADMIN_V1 + "/file")
public class FileController
{
private final MinioService minioService;
public FileController(MinioService minioService) {
this.minioService = minioService;
}
@Operation(summary = "删除文件")
@PostMapping("/delete")
public void deleteImageFile(@RequestBody FileDelParam request) {
String objectName = minioService.getObjectName(request.path);
minioService.deleteImage(objectName);
}
@Operation(summary = "上传图片")
@PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public String uploadImageFile(@RequestParam("file") MultipartFile file) {
return minioService.uploadImage(file, System.currentTimeMillis() + ".jpg");
}
@Operation(summary = "图片转base64")
@PostMapping("/faceBase64")
public String urlToBase64(@RequestBody FaceUploadParam param) {
String objectName = minioService.getObjectName(param.getFileUrl());
return minioService.getImageAsBase64(objectName);
}
}