Spring Boot集成Minio笔记

发布于:2025-03-05 ⋅ 阅读:(16) ⋅ 点赞:(0)

一、首先配置MinIO

1、MinIO新建Bucket,访问控制台如图

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
创建访问密钥(就是账号和密码)
在这里插入图片描述
在这里插入图片描述

二、集成mino添加Minio客户端依赖

1.maven构建方式在pom.xml引入jar

<dependency>
        <groupId>io.minio</groupId>
        <artifactId>minio</artifactId>
        <version>8.4.3</version>
    </dependency>

2.配置Minio连接参数

Springoot配置文件yaml添加minio配置Minio连接参数:

    # minio 参数配置
    minio:
        #是否启用 默认值是true
        enabled: true
        #是否https ,#如果是true,则用的是https而不是http,默认值是false
        secure: false
        #文件预览地址 由于我们的MinIO服务运行在9001端口上
        preview: http://127.0.0.1:9001
        #Minio服务器地址
        endpoint: http://127.0.0.1:9001
        # 默认存储桶
        bucket-name: 
        #登录账号
        access-key: MKBgpZsb7WoLFEUTeR8y
        #登录密码
        secret-key: VpONfVhjGtPOUd26yPrm3ZskvuPLF4QGSTMtWRLE

(endpoint, access key, secret key,bucket name)主要是就是四个个参数,其他是因为业务需要加的参数
在这里插入图片描述

三、编写服务类,实现文件上传、下载等方法

1.创建配置类,初始化MinioClient Bean

import io.minio.MinioClient;
import lombok.Data;
import okhttp3.OkHttpClient;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;

@ConfigurationProperties(prefix = "oss.minio")
@Configuration
@Data
public class MinioConfig {
    /**
     * 服务地址
     */
    private String endpoint;

    /**
     * 文件预览地址
     */
    private String preview;

    /**
     * 存储桶名称
     */
    private String bucketName;

    /**
     * 用户名
     */
    private String accessKey;

    /**
     * 密码
     */
    private String secretKey;

    /**
     * 是否https ,是:true  不是:false
     */
    private Boolean secure;


    /**
     * 初始化客户端,获取 MinioClient
     */
    @Bean
    public MinioClient minioClient() throws NoSuchAlgorithmException, KeyManagementException {
        MinioClient.Builder minioClient = MinioClient.builder()
                .endpoint(endpoint)
                .credentials(accessKey, secretKey);
        //是否https,如果是取消ssl认证
        if (secure) {
            final TrustManager[] trustAllCerts = new TrustManager[]{
                    new X509TrustManager() {
                        @Override
                        public void checkClientTrusted(X509Certificate[] x509Certificates, String s) {
                        }

                        @Override
                        public void checkServerTrusted(X509Certificate[] x509Certificates, String s) {
                        }

                        @Override
                        public X509Certificate[] getAcceptedIssuers() {
                            return new X509Certificate[]{};
                        }
                    }
            };

            X509TrustManager x509TrustManager = (X509TrustManager) trustAllCerts[0];
            final SSLContext sslContext = SSLContext.getInstance("SSL");
            sslContext.init(null, trustAllCerts, new SecureRandom());
            final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
            OkHttpClient.Builder builder = new OkHttpClient.Builder();
            builder.sslSocketFactory(sslSocketFactory, x509TrustManager);

            builder.hostnameVerifier((s, sslSession) -> true);
            OkHttpClient okHttpClient = builder.build();

            minioClient.httpClient(okHttpClient).region("eu-west-1");
        }
        return minioClient.build();
    }

}

2.文件上传接口

package priv.cl.oss.service;

import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;

/**
 * @ClassName MinioFileStorageService
 * @Description MinioFileStorageService
 * @Author cl
 * @Date 2025/2/22 16:40
 */
public interface MinIOFileStorageService {
    /**
     * 上传图片文件
     *
     * @param prefix      文件前缀
     * @param filename    文件名
     * @param inputStream 文件流
     * @return 文件url
     */
    String uploadImgFile(String prefix, String filename, InputStream inputStream);

    /**
     * 上传html文件
     *
     * @param prefix      文件前缀
     * @param filename    文件名
     * @param inputStream 文件流
     * @return 文件url
     */
    String uploadHtmlFile(String prefix, String filename, InputStream inputStream);

    /**
     * 上传文件不分类型
     *
     * @param prefix        文件前缀
     * @param filename      文件名
     * @param multipartFile 文件
     * @return 文件url
     */
    String uploadFileByMultipartFile(String prefix, String filename, MultipartFile multipartFile);

    /**
     * 上传本地文件
     *
     * @param prefix     文件前缀
     * @param objectName 对象名称
     * @param fileName   本地文件路径
     */
    String uploadFile(String prefix, String objectName, String fileName);


    /**
     * 下载文件url到本地指定路径
     *
     * @param fileUrl 文件url
     * @param templatePath 指定路径文件夹
     * @return path 本地文件全路径
     */
    String downloadFile(String fileUrl, String templatePath);

    /**
     * 下载文件
     *
     * @param fileUrl 文件url
     * @return
     */
    byte[] downloadFile(String fileUrl);

    /**
     * 删除文件
     *
     * @param fileUrl 文件url
     */
    void deleteFile(String fileUrl);
}

3.文件上传实现类

package priv.cl.oss.service;

import io.minio.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import priv.cl.oss.config.MinioConfig;

import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @ClassName MinIOFileStorageServiceImpl
 * @Description MinIOFileStorageServiceImpl
 * @Author cl
 * @Date 2025/2/22 16:45
 */
@Slf4j
@Service
public class MinIOFileStorageServiceImpl implements MinIOFileStorageService {

    private String separator = "/";

    @Autowired
    private MinioClient minioClient;

    @Autowired
    private MinioConfig minioConfig;


    /**
     * @param dirPath
     * @param filename yyyy/mm/dd/file.jpg
     * @return
     */
    public String builderFilePath(String dirPath, String filename) {
        StringBuilder stringBuilder = new StringBuilder(50);
        if (!StringUtils.isEmpty(dirPath)) {
            stringBuilder.append(dirPath).append(separator);
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
        String todayStr = sdf.format(new Date());
        stringBuilder.append(todayStr).append(separator);
        stringBuilder.append(filename);
        return stringBuilder.toString();
    }

    /**
     * 获取文件名
     * @param fileUrl
     * @return
     */
    public String getFilePathByFileUrl(String fileUrl) {
        String filePath = fileUrl.replace(minioConfig.getEndpoint() + "/", "");
        int index = filePath.indexOf(separator);
        filePath = filePath.substring(index + 1);
        return filePath;
    }

    /**
     * 上传图片文件
     *
     * @param prefix      文件前缀
     * @param filename    文件名
     * @param inputStream 文件流
     * @return url
     */
    @Override
    public String uploadImgFile(String prefix, String filename, InputStream inputStream) {
        String filePath = builderFilePath(prefix, filename);
        try {
            PutObjectArgs putObjectArgs = PutObjectArgs.builder().object(filePath).contentType("image/jpg").bucket(minioConfig.getBucketName()).stream(inputStream, inputStream.available(), -1).build();
            minioClient.putObject(putObjectArgs);
            StringBuilder urlPath = new StringBuilder(minioConfig.getPreview());
            urlPath.append(separator + minioConfig.getBucketName());
            urlPath.append(separator);
            urlPath.append(filePath);
            return urlPath.toString();
        } catch (Exception e) {
            log.error("minio put file error.", e);
            throw new RuntimeException("上传文件失败");
        }
    }

    /**
     * 上传html文件
     *
     * @param prefix      文件前缀
     * @param filename    文件名
     * @param inputStream 文件流
     * @return url
     */
    @Override
    public String uploadHtmlFile(String prefix, String filename, InputStream inputStream) {
        String filePath = builderFilePath(prefix, filename);
        try {
            PutObjectArgs putObjectArgs = PutObjectArgs.builder().object(filePath).contentType("text/html").bucket(minioConfig.getBucketName()).stream(inputStream, inputStream.available(), -1).build();
            minioClient.putObject(putObjectArgs);
            StringBuilder urlPath = new StringBuilder(minioConfig.getEndpoint());
            urlPath.append(separator + minioConfig.getBucketName());
            urlPath.append(separator);
            urlPath.append(filePath);
            return urlPath.toString();
        } catch (Exception e) {
            log.error("minio put file error.", e);
            throw new RuntimeException("上传文件失败");
        }
    }

    /**
     * 上传文件不分类型
     *
     * @param prefix        文件前缀
     * @param filename      文件名
     * @param multipartFile 文件流
     * @return url
     */
    @Override
    public String uploadFileByMultipartFile(String prefix, String filename, MultipartFile multipartFile) {

        String filePath = builderFilePath(prefix, filename);
        try {
            // 将MultipartFile转换为InputStream
            InputStream inputStream = multipartFile.getInputStream();
            PutObjectArgs putObjectArgs = PutObjectArgs.builder().object(filePath).contentType(multipartFile.getContentType()).bucket(minioConfig.getBucketName()).stream(inputStream, multipartFile.getSize(), -1).build();
            minioClient.putObject(putObjectArgs);
            StringBuilder urlPath = new StringBuilder(minioConfig.getPreview());
            urlPath.append(separator + minioConfig.getBucketName());
            urlPath.append(separator);
            urlPath.append(filePath);
            return urlPath.toString();
        } catch (Exception e) {
            log.error("minio put file error.", e);
            throw new RuntimeException("上传文件失败");
        }
    }


    /**
     * 上传本地文件
     *
     * @param prefix     文件前缀
     * @param objectName 文件名称
     * @param fileName   本地文件全路径
     */
    @Override
    public String uploadFile(String prefix, String objectName, String fileName) {
        String filePath = builderFilePath(prefix, objectName);
        try {
            UploadObjectArgs uploadObjectArgs = UploadObjectArgs.builder().bucket(minioConfig.getBucketName()).object(filePath).filename(fileName).build();
            minioClient.uploadObject(uploadObjectArgs);
            StringBuilder urlPath = new StringBuilder(minioConfig.getEndpoint());
            urlPath.append(separator + minioConfig.getBucketName());
            urlPath.append(separator);
            urlPath.append(filePath);
            return urlPath.toString();
        } catch (Exception e) {
            log.error("minio upload file error.", e);
            throw new RuntimeException("上传文件失败");
        }
    }

    /**
     * 下载文件url到本地指定文件夹
     *
     * @param fileUrl      文件url
     * @param templatePath 指定路径文件夹
     * @return path 本地文件全路径
     */
    @Override
    public String downloadFile(String fileUrl, String templatePath) {
        String filePath = getFilePathByFileUrl(fileUrl);
        InputStream inputStream = null;
        String filename = filePath.substring(filePath.lastIndexOf(separator) + 1);
        try {
            inputStream = minioClient.getObject(GetObjectArgs.builder().bucket(minioConfig.getBucketName()).object(filePath).build());

            FileOutputStream outputStream = null;
            outputStream = new FileOutputStream(templatePath + filename);
            byte[] buff = new byte[100];
            int rc = 0;
            while (true) {
                try {
                    if (!((rc = inputStream.read(buff, 0, 100)) > 0)) break;
                } catch (IOException e) {
                    log.error("文件read失败");
                    e.printStackTrace();
                }
                outputStream.write(buff, 0, rc);
            }
            outputStream.close();
            inputStream.close();
        } catch (Exception e) {
            log.error("minio down file error.  pathUrl:{}", fileUrl);
            throw new RuntimeException("下载文件url到本地指定文件夹失败");
        }
        return templatePath + filename;
    }

    /**
     * 下载文件
     *
     * @param fileUrl 文件全路径
     * @return 文件流
     */
    @Override
    public byte[] downloadFile(String fileUrl) {
        String filePath = getFilePathByFileUrl(fileUrl);

        InputStream inputStream = null;
        try {
            inputStream = minioClient.getObject(GetObjectArgs.builder().bucket(minioConfig.getBucketName()).object(filePath).build());

            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            byte[] buff = new byte[100];
            int rc = 0;
            while (true) {
                try {
                    if (!((rc = inputStream.read(buff, 0, 100)) > 0)) break;
                } catch (IOException e) {
                    log.error("文件read失败");
                    e.printStackTrace();
                }
                byteArrayOutputStream.write(buff, 0, rc);
            }
            return byteArrayOutputStream.toByteArray();
        } catch (Exception e) {
            log.error("minio down file error.  pathUrl:{}", fileUrl);
            throw new RuntimeException("下载文件失败");
        }
    }

    /**
     * 删除文件
     *
     * @param fileUrl 文件url
     */
    @Override
    public void deleteFile(String fileUrl) {
        String filePath = getFilePathByFileUrl(fileUrl);
        // 构建参数
        RemoveObjectArgs removeObjectArgs = RemoveObjectArgs.builder().bucket(minioConfig.getBucketName()).object(filePath).build();
        try {
            minioClient.removeObject(removeObjectArgs);
        } catch (Exception e) {
            log.error("minio remove file error.  pathUrl:{}", fileUrl);
            throw new RuntimeException("删除文件失败");
        }
    }
}

4.Controller调用

@RestController
@RequestMapping("/minio")
public class MinioController {

    @Autowired
    private MinIOFileStorageService minIOFileStorageServiceImpl;

    @GetMapping("/test")
    public String test(){
        return "Hello World";
    }

    @PostMapping("/fileupload")
    public String fileupload(@RequestParam MultipartFile file){
        // 检查multipartFile是否为空
        if (file == null || file.isEmpty()) {
            return "文件为空,无法处理。";
        }
        // 上传到MinIO服务器
        // 这里的"common"是前缀
        String url = minIOFileStorageServiceImpl.uploadFileByMultipartFile("common", file.getOriginalFilename(), file);
        return url;
    }

}

四、测试集成

1.postman调用

在这里插入图片描述

2.通过minio客户端查看

在这里插入图片描述
遇到问题
1.url无法查看在这里插入图片描述
解决方案:
权限问题,设置成pulic,当然为了安全也可以生成访问外链
在这里插入图片描述

至此结束 ,有问题欢迎留言指出谢谢!


网站公告

今日签到

点亮在社区的每一天
去签到