当前位置: 首页 > news >正文

如何在springboot项目中使用minio上传下载删除文件

引入maven依赖

<!--  minio   -->
<dependency><groupId>io.minio</groupId><artifactId>minio</artifactId><version>8.2.2</version>
</dependency>

申请 bucket | access_key | secret_key

项目中配置相关参数

    minio:# access_keyaccessKey: xxxxxx# secret_keysecretKey: xxxxxx# bucketbucketName: bucket1# 内网地址endpoint: http://127.0.0.1:9000# 外网地址website: https://xxx.xxx.cn:9000# 自定义文件大小限制 注:要与spring.servlet.multipart.max-file-size | max-request-size 区分开maxFileSize:img: 10video: 30

endpoint | website | maxFileSize 可根据项目需要增删,后面不再赘述。

Minio 配置信息


/*** Minio 配置信息** @author ruoyi*/
@Configuration
@ConfigurationProperties(prefix = "minio")
public class MinioConfig
{/*** 用户名*/private String accessKey;/*** 密码*/private String secretKey;/*** 存储桶名称*/private String bucketName;/*** 服务地址*/private String endpoint;/*** 公网*/private String webSite;/*** 文件大小限制*/private MediaMaxFileSize maxFileSize;public static class MediaMaxFileSize{private Long img;private Long video;public Long getImg() {return img;}public void setImg(Long img) {this.img = img;}public Long getVideo() {return video;}public void setVideo(Long video) {this.video = video;}}public String getWebSite() {return webSite;}public void setWebSite(String webSite) {this.webSite = webSite;}public MediaMaxFileSize getMaxFileSize() {return maxFileSize;}public void setMaxFileSize(MediaMaxFileSize maxFileSize) {this.maxFileSize = maxFileSize;}public String getAccessKey() {return accessKey;}public void setAccessKey(String accessKey) {this.accessKey = accessKey;}public String getSecretKey() {return secretKey;}public void setSecretKey(String secretKey) {this.secretKey = secretKey;}public String getBucketName() {return bucketName;}public void setBucketName(String bucketName) {this.bucketName = bucketName;}public String getEndpoint() {return endpoint;}public void setEndpoint(String endpoint) {this.endpoint = endpoint;}@Beanpublic MinioClient getMinioClient() {return MinioClient.builder().endpoint(endpoint).credentials(accessKey, secretKey).build();}
}

/*** 文件对象实体类*/
public class MinioFile implements Serializable {// 文件服务器文件所属组private String bucketName;// 不带文件组的文件URLprivate String path;// 带文件组的文件URLprivate String fullPath;// 站点信息private String webSite;// 带站点的文件URLprivate String webUrl;// 原始文件名private String fileName;// 内网廉价而private String intranetWebSite;// 内网地址private String intranetWebUrl;// 其他参数private Map<String, Object> params = new HashMap<>();public String getFullPath() {return fullPath;}public void setFullPath(String fullPath) {this.fullPath = fullPath;}public String getPath() {return path;}public void setPath(String path) {this.path = path;}public String getWebSite() {return webSite;}public void setWebSite(String webSite) {this.webSite = webSite;}public String getWebUrl() {return webUrl;}public void setWebUrl(String webUrl) {this.webUrl = webUrl;}public String getFileName() {return fileName;}public void setFileName(String fileName) {this.fileName = fileName;}public String getIntranetWebUrl() {return intranetWebUrl;}public void setIntranetWebUrl(String intranetWebUrl) {this.intranetWebUrl = intranetWebUrl;}public String getIntranetWebSite() {return intranetWebSite;}public void setIntranetWebSite(String intranetWebSite) {this.intranetWebSite = intranetWebSite;}public String getBucketName() {return bucketName;}public void setBucketName(String bucketName) {this.bucketName = bucketName;}public Map<String, Object> getParams() {if (params == null) {params = new HashMap<>();}return params;}public void setParams(Map<String, Object> params) {this.params = params;}public Object getParam(String key) {if (params == null) {params = new HashMap<>();return null;}return params.get(key);}public void putParam(String key, Object value) {if (params == null) {params = new HashMap<>();}params.put(key, value);}}

文件上传下载删除工具类封装

项目基于RuoYi开源框架搭建,因此此处工具类引入开源框架中一些内置工具类


import com.ruoyi.common.exception.file.InvalidExtensionException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.common.utils.file.MimeTypeUtils;
import com.ruoyi.common.utils.uuid.Seq;
import io.minio.GetPresignedObjectUrlArgs;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import io.minio.RemoveObjectArgs;
import io.minio.http.Method;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;import java.io.IOException;
import java.io.InputStream;
import java.util.Date;/*** Minio 文件存储工具类* * @author ruoyi*/
@Component
public class MinioUtil
{private static Logger log = LoggerFactory.getLogger(MinioUtil.class);/*** minio实例*/private static MinioClient minioClient;/*** minio配置类*/private static MinioConfig minioConfig;@Autowiredpublic void setMinioUtil(MinioClient minioClient, MinioConfig minioConfig){MinioUtil.minioClient = minioClient;MinioUtil.minioConfig = minioConfig;}public MinioFile uploadFile(MultipartFile file, String fileType, String filePurpose) throws InvalidExtensionException, IOException {if("01".equals(fileType)){FileUploadUtils.assertAllowed(file, MimeTypeUtils.IMAGE_EXTENSION_10001, minioConfig.getMaxFileSize().getImg() * 1024 * 1024);} else if ("02".equals(fileType)) {FileUploadUtils.assertAllowed(file, MimeTypeUtils.VIDEO_EXTENSION_10002, minioConfig.getMaxFileSize().getVideo() * 1024 * 1024);}// 年月String yyyyMM = DateUtils.parseDateToStr("yyyyMM", new Date());// 文件名 moduleName/业务类型/文件类型/年月/Seq随机字符/文件后缀String fileName = StringUtils.format("{}/{}/{}/{}/{}.{}","moduleName", getFilePurpose(filePurpose)// 使用用途, getFileType(fileType)//文件类型, yyyyMM, Seq.getId(), FileUploadUtils.getExtension(file));return uploadFile(file, fileName);}private MinioFile uploadFile(MultipartFile file, String fileName) throws IOException {String webUrl = uploadFile(minioConfig.getBucketName(), fileName, file);MinioFile minioFile = new MinioFile();minioFile.setBucketName(minioConfig.getBucketName());minioFile.setPath(fileName);minioFile.setFullPath(StringUtils.format("{}/{}",minioConfig.getBucketName(),fileName));minioFile.setWebSite(minioConfig.getWebSite());minioFile.setWebUrl(webUrl.replace(minioConfig.getEndpoint(),minioConfig.getWebSite()));minioFile.setFileName(file.getOriginalFilename());minioFile.setIntranetWebSite(minioConfig.getEndpoint());minioFile.setIntranetWebUrl(webUrl);return minioFile;}/*** 上传文件* * @param bucketName 桶名称* @param fileName* @throws IOException*/private String uploadFile(String bucketName, String fileName, MultipartFile multipartFile) throws IOException{String url = "";try (InputStream inputStream = multipartFile.getInputStream()){minioClient.putObject(PutObjectArgs.builder().bucket(bucketName).object(fileName).stream(inputStream, multipartFile.getSize(), -1).contentType(multipartFile.getContentType()).build());url = minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder().bucket(bucketName).object(fileName).method(Method.GET).build());url = url.substring(0, url.indexOf('?'));return ServletUtils.urlDecode(url);}catch (Exception e){throw new IOException(e.getMessage(), e);}}/*** 删除文件* @param fileName*/public void removeFile(String fileName){try{minioClient.removeObject(RemoveObjectArgs.builder().bucket(minioConfig.getBucketName()).object(fileName).build());}catch (Exception e){e.printStackTrace();log.error("MinioUtil-uploadMinio-error", e);}}/*** 文件类型 可自定义* @param fileType* @return*/private String getFileType(String fileType){String fileTypeName = null;switch (fileType){case "01":fileTypeName = "image";break;case "02":fileTypeName = "video";break;default:fileTypeName = "undefined";}return fileTypeName;}/*** 获取文件使用用途 可自定义* @param filePurpose* @return*/private String getFilePurpose(String filePurpose){String filePurposeType = null;switch (filePurpose){case "01":filePurposeType = "banner";break;default:filePurposeType = "undefined";}return filePurposeType;}}

MimeTypeUtils.IMAGE_EXTENSION_10001 和 MimeTypeUtils.VIDEO_EXTENSION_10002为在原框架工具类上新增自定义文件后缀
另根据业务需要,对框架FileUploadUtils中的assertAllowed进行方法重载

/*** 文件大小校验** @param file 上传的文件* @return* @throws FileSizeLimitExceededException 如果超出最大大小* @throws InvalidExtensionException*/public static final void assertAllowed(MultipartFile file, String[] allowedExtension)throws FileSizeLimitExceededException, InvalidExtensionException{assertAllowed(file, allowedExtension, DEFAULT_MAX_SIZE);}/*** 文件大小校验** @param file 上传的文件* @param maxSize 最大限制* @return* @throws FileSizeLimitExceededException 如果超出最大大小* @throws InvalidExtensionException*/public static final void assertAllowed(MultipartFile file, String[] allowedExtension, long maxSize)throws FileSizeLimitExceededException, InvalidExtensionException{long size = file.getSize();if (size > maxSize){throw new FileSizeLimitExceededException(maxSize / 1024 / 1024);}String fileName = file.getOriginalFilename();String extension = getExtension(file);if (allowedExtension != null && !isAllowedExtension(extension, allowedExtension)){if (allowedExtension == MimeTypeUtils.IMAGE_EXTENSION){throw new InvalidExtensionException.InvalidImageExtensionException(allowedExtension, extension,fileName);}else if (allowedExtension == MimeTypeUtils.FLASH_EXTENSION){throw new InvalidExtensionException.InvalidFlashExtensionException(allowedExtension, extension,fileName);}else if (allowedExtension == MimeTypeUtils.MEDIA_EXTENSION){throw new InvalidExtensionException.InvalidMediaExtensionException(allowedExtension, extension,fileName);}else if (allowedExtension == MimeTypeUtils.VIDEO_EXTENSION){throw new InvalidExtensionException.InvalidVideoExtensionException(allowedExtension, extension,fileName);}else if (allowedExtension == MimeTypeUtils.IMAGE_EXTENSION_10001){throw new InvalidExtensionException.InvalidImageExtensionException(allowedExtension, extension,fileName);}else if (allowedExtension == MimeTypeUtils.VIDEO_EXTENSION_10002){throw new InvalidExtensionException.InvalidVideoExtensionException(allowedExtension, extension,fileName);}else{throw new InvalidExtensionException(allowedExtension, extension, fileName);}}}

相关文章:

如何在springboot项目中使用minio上传下载删除文件

引入maven依赖 <!-- minio --> <dependency><groupId>io.minio</groupId><artifactId>minio</artifactId><version>8.2.2</version> </dependency>申请 bucket | access_key | secret_key 项目中配置相关参数 mini…...

SSM个性化旅游管理系统开发mysql数据库web结构java编程计算机网页源码eclipse项目

一、源码特点 SSM 个性化旅游管理系统是一套完善的信息系统&#xff0c;结合springMVC框架完成本系统&#xff0c;对理解JSP java编程开发语言有帮助系统采用SSM框架&#xff08;MVC模式开发&#xff09;&#xff0c;系统具有完整的源代码和数据库 &#xff0c;系统主要采用B…...

4-Docker命令之docker version

1.docker version介绍 docker version命令是用于查看docker容器的版本信息 2.docker version用法 docker version [参数] [root@centos79 ~]# docker version --helpUsage: docker version [OPTIONS]Show the Docker version informationOptions:-f, --format string Fo…...

Redis高并发缓存架构

前言&#xff1a; 针对缓存我们并不陌生&#xff0c;而今天所讲的是使用redis作为缓存工具进行缓存数据。redis缓存是将数据保存在内存中的&#xff0c;而内存的珍贵性是不可否认的。所以在缓存之前&#xff0c;我们需要明确缓存的对象&#xff0c;是否有必要缓存&#xff0c;怎…...

谨防利用Redis未授权访问漏洞入侵服务器

说明&#xff1a; Redis是一个开源的&#xff0c;由C语言编写的高性能NoSQL数据库&#xff0c;因其高性能、可扩展、兼容性强&#xff0c;被各大小互联网公司或个人作为内存型存储组件使用。 但是其中有小部分公司或个人开发者&#xff0c;为了方便调试或忽略了安全风险&#…...

关于一些bug的解决1、el-input的输入无效2、搜索之后发现数据不对3、el多选框、单选框点击无用4、

el-input输入无效 原来的代码是 var test null 但是我发现不能输入任何值 反倒修改test的初始值为123是可以的 于是我确定绑定没问题 就是修改的问题 于是改成 var test ref&#xff08;&#xff09; v-model绑定的值改成test.value就可以了 因为ref是相应式的 可以通过输入…...

使用 JavaScript 进行 API 测试的综合教程

说明 API 测试是软件测试的一种形式&#xff0c;涉及直接测试 API 并作为集成测试的一部分&#xff0c;以确定它们是否满足功能、可靠性、性能和安全性的预期。 先决条件&#xff1a; JavaScript 基础知识。Node.js 安装在您的计算机上。如果没有&#xff0c;请在此处下载。npm…...

Vue 2.0源码分析-Virtual DOM

Virtual DOM 这个概念相信大部分人都不会陌生&#xff0c;它产生的前提是浏览器中的 DOM 是很“昂贵"的&#xff0c;为了更直观的感受&#xff0c;我们可以简单的把一个简单的 div 元素的属性都打印出来&#xff0c;如图所示&#xff1a; 可以看到&#xff0c;真正的 DOM …...

(HAL库版)freeRTOS移植STMF103

正点原子关于freeRTOS的教程是比较好的&#xff0c;可惜移植的是标准库&#xff0c;但是我学的是Hal库&#xff0c;因为开发速度更快&#xff0c;从最后那个修改SYSTEM文件夹的地方开始替换为下面的内容就可以了 5.修改Systick中断、SVC中断、PendSV中断 将SVC中断、P…...

vue2-axios

下载axios 开发版本&#xff1a;axios.js 生产版本&#xff1a;axios.min.js 搭建服务器&#xff1a;json-server npm i -g json-serverjson-server --watch db.json&#xff08;启动服务并读取文件&#xff0c;db.json文件目录下启动&#xff09; json-server --watch db.j…...

创建maven的web项目

&#xff08;一&#xff09;创建maven的web项目 Step1、创建一个普通的maven项目 &#xff08;1&#xff09;新建一个empty project&#xff0c;命名为SSM2。 点击项目名&#xff0c;右键new&#xff0c;选择Module&#xff0c;左侧选择“Maven archetype”&#xff0c;可以给…...

使用uniapp开发系统懒加载图片效果

1、创建一个Vue组件 在uniapp项目中&#xff0c;我们可以创建一个独立的Vue组件来实现懒加载图片效果。打开uniapp项目&#xff0c;进入components文件夹&#xff0c;创建一个名为"LazeImage"的组件。 2、编写组件模板 在"LazeImage"组件中&#xff0c;…...

导入PIL时报错

在导入PIL时,报以下错误: 查找原因 参考博客 Could not find a version that satisfies the requirement PIL (from versions: ) No matching distributi-CSDN博客,按照wheel后,安装PIL时,报如下的错误。 查找说是python版本与wheel文件版本不同,确认本机python版本 …...

MyBatis Generator 插件 详解自动生成代码

MyBatis Generator&#xff08;MBG&#xff09;是MyBatis和iBATIS的代码生成器。可以生成简单CRUD操作的XML配置文件、Mapper文件(DAO接口)、实体类。实际开发中能够有效减少程序员的工作量&#xff0c;甚至不用程序员手动写sql。 它将为所有版本的MyBatis以及版本2.2.0之后的i…...

SkyWalking全景解析:从原理到实现的分布式追踪之旅

&#x1f38f;&#xff1a;你只管努力&#xff0c;剩下的交给时间 &#x1f3e0; &#xff1a;小破站 SkyWalking全景解析&#xff1a;从原理到实现的分布式追踪之旅 前言第一&#xff1a;SkyWalking简介第二&#xff1a;实现原理概览第三&#xff1a;主键与架构第四&#xff1…...

新手如何买卖可转债,可转债投资基础入门

一、教程描述 什么是可转债&#xff1f;可转债是可转换债券的二次简称&#xff0c;原始全称是可转换公司债券&#xff0c;这是一种可以在特定时间、按特定条件&#xff0c;转换为普通股票的特殊企业债券&#xff0c;可转换债券兼具债权和股权的特征&#xff0c;其英文为conver…...

研习代码 day39 | 动态规划——完全背包的应用

一、爬楼梯&#xff08;进阶版&#xff09; 1.1 题目 题目描述 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬至多m (1 < m < n)个台阶。你有多少种不同的方法可以爬到楼顶呢&#xff1f; 注意&#xff1a;给定 n 是一个正整数。 输入描述 输入共一…...

Rust语言入门教程(五) - 流控制语句

if 表达式 在Rust中&#xff0c; if语句的判断条件不需要用( )括起来&#xff0c; 它会认为所有在if 和 {之间的表达式就是判断条件&#xff0c;例如&#xff1a; if num 5 {msg "five"; }判断条件的表达式必须返回一个bool型的值&#xff0c; 因为Rust是一个不喜…...

字符串:leetcode1410. HTML 实体解析器

1410. HTML 实体解析器 「HTML 实体解析器」 是一种特殊的解析器&#xff0c;它将 HTML 代码作为输入&#xff0c;并用字符本身替换掉所有这些特殊的字符实体。 HTML 里这些特殊字符和它们对应的字符实体包括&#xff1a; 双引号&#xff1a;字符实体为 &quot; &#xff…...

springboot+vue项目如何集成onlyoffice开源文档组件

一、onlyoffice是什么 ONLYOFFICE 是一个开源的办公套件&#xff0c;适合多人在线协作。由总部位于总部在拉脱维亚的 IT 公司Acensio System SIA 开发。它提供在线协作文档编辑器&#xff08;包括文档、电子表格、演示文稿和表单&#xff09;&#xff0c;适用于 Windows、Linu…...

艺术鉴赏零门槛:丹青识画智能系统,小白也能秒懂名画意境

艺术鉴赏零门槛&#xff1a;丹青识画智能系统&#xff0c;小白也能秒懂名画意境 1. 当科技遇见艺术&#xff1a;重新定义影像理解 站在美术馆的名画前&#xff0c;你是否曾感到困惑——明明被画面打动&#xff0c;却说不出所以然&#xff1f;或是精心拍摄的照片&#xff0c;总…...

高效自动化视频剪辑:Python剪映API终极指南

高效自动化视频剪辑&#xff1a;Python剪映API终极指南 【免费下载链接】JianYingApi Third Party JianYing Api. 第三方剪映Api 项目地址: https://gitcode.com/gh_mirrors/ji/JianYingApi 剪映自动化、Python视频处理、批量剪辑、第三方API、视频编辑自动化——这些技…...

从零实现地震波场模拟:交错网格有限差分法核心代码精讲

1. 从零理解地震波场模拟的核心概念 地震波场模拟是计算地球物理学中最基础也最重要的技术之一。想象一下&#xff0c;当地震发生时&#xff0c;地面会像水面波纹一样产生震动&#xff0c;这些震动在地球内部传播的过程就是地震波场。我们通过计算机模拟这个过程&#xff0c;可…...

宁德时代6分钟超充发布-动力电池进入秒充时代

宁德时代6分钟超充发布&#xff1a;动力电池进入"秒充时代" 一、技术突破&#xff1a;从"里程焦虑"到"补能自由" 2026年4月21日&#xff0c;宁德时代在北京举办2026"极域之约"超级科技日新品发布会&#xff0c;震撼推出多款新型电池产…...

别再乱接线了!ESP32-S3固件烧录保姆级硬件自查清单(含常见失败原因)

ESP32-S3固件烧录失败&#xff1f;这份硬件自查清单能救你 刚拿到ESP32-S3开发板时&#xff0c;那种跃跃欲试的心情我至今记得。但当我按照教程接好线&#xff0c;点击烧录按钮后&#xff0c;屏幕上却跳出"等待上电同步"的提示&#xff0c;那一刻的挫败感同样记忆犹新…...

别再死记硬背了!手把手教你用Python生成PRBS序列(附PRBS3/9/31代码)

用Python实现PRBS序列生成&#xff1a;从理论到实战的完整指南 在数字通信和测试领域&#xff0c;伪随机二进制序列(PRBS)扮演着至关重要的角色。这种看似随机却具有确定性的比特流&#xff0c;广泛应用于信道编码、系统测试和加密算法等多个场景。不同于简单的随机数生成&…...

永磁同步电机智能控制技术:模糊逻辑与神经网络应用

1. 永磁同步电机智能控制技术演进永磁同步电机(PMSM)作为现代工业驱动系统的核心部件&#xff0c;其控制性能直接影响着电动汽车、工业机器人等高精度应用场景的能效表现。传统PID控制在面对参数变化和外部扰动时表现出的局限性&#xff0c;促使研究者将目光转向更具鲁棒性的控…...

登录无法连接sqlserver数据库手顺

这个 Cant open lib ODBC Driver 17 for SQL Server : file not found 错误&#xff0c;是系统提示找不到 SQL Server 的 ODBC 驱动&#xff0c;通常因为驱动未安装、未正确配置或缺少依赖。 安装驱动、创建数据源&#xff08;DSN&#xff09;并测试连接&#xff0c;可以按以下…...

PyTorch实现线性回归:从基础到实战

1. 线性预测的基础概念线性预测是机器学习中最基础也最重要的建模方式之一。在PyTorch框架中实现线性预测模型&#xff0c;不仅能够帮助我们理解深度学习的底层原理&#xff0c;也是掌握更复杂神经网络架构的必要前提。线性模型的核心思想可以用一个简单的数学公式表示&#xf…...

ESP32玩转网络转发:除了做中继,你的AP+STA模式还能这样用(附IoT项目思路)

ESP32网络转发进阶指南&#xff1a;解锁APSTA模式的5种创新应用 在物联网开发领域&#xff0c;ESP32的APSTA双模工作能力常被简化为无线中继功能&#xff0c;这就像只使用瑞士军刀的剪刀功能而忽略了其他十几种工具。实际上&#xff0c;这种双模协同能够实现更复杂的网络架构设…...