简介
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);
    }
}点击查看更多内容
					为 TA 点赞
										
				 评论
				共同学习,写下你的评论
评论加载中...
作者其他优质文章
					正在加载中
				
			感谢您的支持,我会继续努力的~
		扫码打赏,你说多少就多少
		赞赏金额会直接到老师账户
		支付方式
		打开微信扫一扫,即可进行扫码打赏哦
	
                
            


