Spring Boot集成Minio笔记

news2025/3/12 6:10:00

一、首先配置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,当然为了安全也可以生成访问外链
在这里插入图片描述

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2311645.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

HCIA-路由重分布

一、路由重分布是指在同一个网络中&#xff0c;将一种路由协议所学习到的路由信息导入到另一种路由协议中的技术&#xff0c;实现通信。 二、实验 1、配置 AR1AR2AR3sy sy AR1 int g 0/0/1 ip add 192.168.1.254 24 int g 0/0/0 ip add 10.1.1.1 24 rip version 2 net 192.16…

【项目】nnUnetv2复现

作者提出一种nnUNet(no-new-Net)框架,基于原始的UNet(很小的修改),不去采用哪些新的结构,如相残差连接、dense连接、注意力机制等花里胡哨的东西。相反的,把重心放在:预处理(resampling和normalization)、训练(loss,optimizer设置、数据增广)、推理(patch-based…

【大学生体质】智能 AI 旅游推荐平台(Vue+SpringBoot3)-完整部署教程

智能 AI 旅游推荐平台开源文档 项目前端地址 ☀️项目介绍 智能 AI 旅游推荐平台&#xff08;Intelligent AI Travel Recommendation Platform&#xff09;是一个利用 AI 模型和数据分析为用户提供个性化旅游路线推荐、景点评分、旅游攻略分享等功能的综合性系统。该系统融合…

TCP7680端口是什么服务

WAF上看到有好多tcp7680端口的访问信息 于是上网搜索了一下&#xff0c;确认TCP7680端口是Windows系统更新“传递优化”功能的服务端口&#xff0c;个人理解应该是Windows利用这个TCP7680端口&#xff0c;直接从内网已经具备更新包的主机上共享下载该升级包&#xff0c;无需从微…

恭喜!《哪吒2》明天将荣登世界影坛第六!目前仅差1.81亿元

全球总票房为为20.27亿美元&#xff01;3月8日将荣登世界影坛第六宝座&#xff01; 中国票房 内地票房 中国电影票房、灯塔、猫眼三大数据源加权平均得出《哪吒2》中国内地总票房为144.26亿元人民币。 港澳票房 目前港澳地区没有新的数据显示&#xff0c;按3月6日1905电影网…

e2studio开发RA4M2(15)----配置RTC时钟及显示时间

e2studio开发RA4M2.15--配置RTC时钟及显示时间 概述视频教学样品申请硬件准备参考程序源码下载新建工程工程模板保存工程路径芯片配置工程模板选择时钟设置SWD调试口设置UART配置UART属性配置设置e2studio堆栈e2studio的重定向printf设置R_SCI_UART_Open()函数原型回调函数user…

Flink深入浅出之04:时间、水印、TableSQL

深入理解Flink的waterMark的机制、Flink Table和SQL开发 3️⃣ 目标 掌握WaterMark的的原理掌握WaterMark的运用掌握Flink Table和SQL开发 4️⃣ 要点 &#x1f4d6; 1. Flink中的Time概念 对于流式数据处理&#xff0c;最大的特点是数据上具有时间的属性特征 Flink根据时…

MongoDB Compass 使用说明

MongoDB Compass 使用说明 安装工具栏按钮详细介绍Connect(连接)1. New Window&#xff08;新窗口&#xff09;2. Disconnect&#xff08;断开连接&#xff09;3. Import Saved Connections&#xff08;导入保存的连接&#xff09;4. Export Saved Connections&#xff08;导出…

Halcon 算子 一维码检测识别、项目案例

首先我们要明白码的识别思路 把窗口全部关闭读取新的图片图像预处理创建条码模型设置模型参数搜索模型获取条码结果显示条码结果 图像预处理和条码增强 对比度太低&#xff1a; scale_image&#xff08;或使用外部程序scale_image_range&#xff09;,增强图像的对比度图像模糊…

信号完整性基础:高速信号的扩频时钟SSC测试

扩频时钟 SSC 是 Spread Spectrum Clock 的英文缩写&#xff0c;目前很多数字电路芯片都支持 SSC 功能&#xff0c;如&#xff1a;PCIE、USB3.0、SATA 等等。那么扩频时钟是用来做什么的呢&#xff1f; SSC背景&#xff1a; 扩频时钟是出于解决电磁干扰&#xff08;EMI&#…

stm32移植LCD2002驱动

介绍 LCD2002支持20X2个字符串显示&#xff0c;引脚功能和读写时序跟LCD1602都很像 LCD类型&#xff1a;字符点阵 点 阵 数&#xff1a;202 外形尺寸&#xff1a;116.0mm37.0mm&#xff08;长宽&#xff09; 视域尺寸&#xff1a;83.0mm18.6mm 点 距 离&#xff1a;0.05mm…

OpenCV计算摄影学(18)平滑图像中的纹理区域同时保留边缘信息函数textureFlattening()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 cv::textureFlattening 是 OpenCV 中用于图像处理的一个函数&#xff0c;旨在平滑图像中的纹理区域&#xff0c;同时保留边缘信息。该技术特别适…

“此电脑”中删除WPS云盘方法(百度网盘通用)

&#x1f4e3;此方法适用于卸载WPS云盘后&#xff0c;WPS云盘图标依然在此电脑中显示的问题。 原理&#xff1a;通过注册来进行删除 步骤&#xff1a; WIN键R,打开运行窗口&#xff0c;输入regedit命令&#xff0c;来打开【注册表编辑器】&#xff1b; 从左侧&#xff0c;依…

Agent革命:Manus如何用工作流拆解掀起AI生产力革命

一、现象级产品的诞生背景 2025年3月6日&#xff0c;一款名为Manus的AI产品在技术圈引发地震式传播。其官方测试数据显示&#xff1a;在GAIA基准测试中&#xff0c;基础任务准确率达86.5%&#xff08;接近人类水平&#xff09;&#xff0c;中高级任务完成率突破57%。这标志着A…

四款GIS工具箱软件解析:满足企业多样化空间数据需求

概述 随着地理信息系统&#xff08;GIS&#xff09;在城市规划、环境监测、资源管理等领域的广泛应用&#xff0c;各种GIS工具箱软件不断涌现&#xff0c;为用户提供了强大的数据处理、空间分析和地图制图功能。本文将为大家介绍4款GIS工具箱软件&#xff0c;这些软件各具特色…

After Effects的图钉与关键帧动画

姜 子 博 引言 在数字媒体时代&#xff0c;动态图形和视觉效果在信息传播和表达中扮演着越来越重要的角色。After Effects 作为行业领先的软件&#xff0c;提供了丰富的工具和功能&#xff0c;帮助用户创作出令人惊叹的视觉作品。图钉工具和关键帧动画是 AE 中实现复杂动画效…

SAP DOI EXCEL宏的使用

OAOR里上传EXCEL模版 屏幕初始化PBO创建DOI EXCEL对象&#xff0c;并填充EXCEL内容 *&---------------------------------------------------------------------* *& Module INIT_DOI_DISPLAY_9100 OUTPUT *&--------------------------------------------…

新编大学应用英语综合教程3 U校园全套参考答案

获取全套答案&#xff1a; 链接&#xff1a;https://pan.quark.cn/s/abaa0338724e

高考數學。。。

2024上 具体来说&#xff0c;直线的参数方程可以写为&#xff1a; x1t y−t z1t 二、简答题(本大题共5小题&#xff0c;每小题7分&#xff0c;共35分。) 12.数学学习评价不仅要关注结果评价&#xff0c;也要关注过程评价。简要说明过程评价应关注哪几个方面。…

STM32 子设备通过CAN发送数据到主设备

采集ADC、GPS经纬坐标、温湿度数据、大气压数据通过CAN方式发送给主设备端&#xff0c;帧ID按照如下定义&#xff1a; 我尼玛一个标准帧ID位数据是11位&#xff0c;扩展帧才是111829位&#xff0c;它说最开头的是四位是真类型&#xff0c;并给我如下解释&#xff1a; 它把帧的定…