SpringBoot集成MinIO8.0
一、安装MinIO
中文官网地址:https://www.minio.org.cn/download.shtml
官网地址:https://min.io/download
官网有相应的安装命令,可查看
建议引用相应版本的依赖

二、集成SpringBoot
1.引入依赖
<dependency><groupId>io.minio</groupId><artifactId>minio</artifactId><version>8.4.3</version>
</dependency>
2.配置文件
# minio配置minio:endpoint: http://124.223.18.203:9000region:access-key: F5PKaRjxGXlbiFmarzF7secret-key: cKL8dQpLoORJ21Gw7882lUIAbA66RGKaKfsl0om2bucket: file
3.配置类
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;/*** 读取项目文件配置** @author qiangesoft*/
@Data
@Component
@ConfigurationProperties(prefix = "minio")
public class MinioProperties {/*** 服务地址*/private String endpoint = "http://127.0.0.1/9000/";/*** 地区*/private String region;/*** 认证账户*/private String accessKey;/*** 认证密码*/private String secretKey;/*** 桶*/private String bucket;}
4.实例化客户端
import com.qiangesoft.rdp.starter.minio.core.MinioTemplate;
import com.qiangesoft.rdp.starter.minio.core.MinioTemplateImpl;
import io.minio.BucketExistsArgs;
import io.minio.MakeBucketArgs;
import io.minio.MinioClient;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.ObjectUtils;/*** minio自动配置** @author qiangesoft* @date 2023-09-15*/
@Slf4j
@Configuration
@ConditionalOnClass(value = {MinioClient.class})
@RequiredArgsConstructor
@EnableConfigurationProperties(MinioProperties.class)
public class MinioConfiguration {private final MinioProperties minioProperties;@Bean@ConditionalOnMissingBeanpublic MinioClient minioClient() {log.info("MinioClient initializing, url is {}, accessKey is {}!", minioProperties.getEndpoint(), minioProperties.getAccessKey());MinioClient.Builder builder = MinioClient.builder().endpoint(minioProperties.getEndpoint()).credentials(minioProperties.getAccessKey(), minioProperties.getSecretKey());String region = minioProperties.getRegion();if (region != null && region.length() > 0) {builder.region(region);}MinioClient minioClient = builder.build();String bucket = minioProperties.getBucket();if (ObjectUtils.isEmpty(bucket)) {log.error("Bucket not empty");throw new RuntimeException("Bucket not empty");}// 初始化桶if (!this.checkExists(minioClient, bucket)) {this.createBucket(minioClient, bucket);}log.info("MinioClient initialization success!");return minioClient;}@Bean@ConditionalOnMissingBeanpublic MinioTemplate minioTemplate() {return new MinioTemplateImpl(minioProperties, minioClient());}/*** 检查桶是否存在** @param minioClient* @param bucketName* @return*/private boolean checkExists(MinioClient minioClient, String bucketName) {try {return minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());} catch (Exception e) {log.error("Check bucket exists failed with error");throw new RuntimeException("Check bucket exists failed with error");}}/*** 创建桶** @param minioClient* @param bucketName*/private void createBucket(MinioClient minioClient, String bucketName) {try {minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());} catch (Exception e) {log.error("Create bucket failed with error");throw new RuntimeException("Create bucket failed with error");}}
}
5.API使用
import io.minio.StatObjectResponse;
import io.minio.messages.Bucket;
import org.springframework.web.multipart.MultipartFile;import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.util.List;/*** minio文件服务** @author qiangesoft* @date 2023-04-21*/
public interface MinioTemplate {/*** 创建桶** @param bucketName* @throws Exception*/void createBucket(String bucketName) throws Exception;/*** 获取桶** @return*/List<Bucket> listBuckets() throws Exception;/*** 获取桶** @param bucketName* @return* @throws Exception*/Bucket getBucket(String bucketName) throws Exception;/*** 删除桶** @param bucketName* @throws Exception*/void removeBucket(String bucketName) throws Exception;/*** 上传文件** @param bucketName* @param inputStream* @param objectName* @return* @throws Exception*/String putObject(String bucketName, InputStream inputStream, String objectName) throws Exception;/*** 上传文件** @param bucketName* @param file* @return* @throws Exception*/String putObject(String bucketName, MultipartFile file) throws Exception;/*** 分享文件地址** @param bucketName* @param objectName* @param expires* @return* @throws Exception*/String getObjectURL(String bucketName, String objectName, Integer expires) throws Exception;/*** 获取文件** @param bucketName* @param objectName* @return* @throws Exception*/InputStream getObject(String bucketName, String objectName) throws Exception;/*** 获取文件** @param bucketName* @param objectName* @return* @throws Exception*/StatObjectResponse getObjectInfo(String bucketName, String objectName) throws Exception;/*** 下载文件** @param bucketName* @param filename* @param response* @throws Exception*/void download(String bucketName, String filename, HttpServletResponse response) throws Exception;/*** 删除文件** @param bucketName* @param objectName* @throws Exception*/void removeObject(String bucketName, String objectName) throws Exception;/*** 删除文件** @param bucketName* @param objectNames* @throws Exception*/void removeObjects(String bucketName, List<String> objectNames) throws Exception;
}
import com.qiangesoft.rdp.starter.minio.config.MinioProperties;
import io.minio.*;
import io.minio.messages.Bucket;
import io.minio.messages.DeleteError;
import io.minio.messages.DeleteObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.Assert;
import org.springframework.util.FastByteArrayOutputStream;
import org.springframework.web.multipart.MultipartFile;import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;/*** minio文件服务实现类** @author qiangesoft* @date 2023-04-21*/
@Slf4j
public class MinioTemplateImpl implements MinioTemplate {private static final String SLASH = "/";private MinioProperties minioProperties;private MinioClient minioClient;public MinioTemplateImpl(MinioProperties minioProperties, MinioClient minioClient) {this.minioProperties = minioProperties;this.minioClient = minioClient;}@Overridepublic void createBucket(String bucketName) throws Exception {BucketExistsArgs args = BucketExistsArgs.builder().bucket(bucketName).build();boolean exists = minioClient.bucketExists(args);if (!exists) {minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());}}@Overridepublic List<Bucket> listBuckets() throws Exception {return minioClient.listBuckets();}@Overridepublic Bucket getBucket(String bucketName) throws Exception {Optional<Bucket> first = this.listBuckets().stream().filter(e -> e.name().equals(bucketName)).findFirst();return first.orElse(null);}@Overridepublic void removeBucket(String bucketName) throws Exception {minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());}@Overridepublic String putObject(String bucketName, InputStream inputStream, String objectName) throws Exception {// 参数校验Assert.notNull(bucketName, "bucketName is not blank");Assert.notNull(inputStream, "inputStream is not null");Assert.notNull(objectName, "objectName is not blank");// 判断存储桶是否存在,不存在则创建this.createBucket(bucketName);// 上传minioClient.putObject(PutObjectArgs.builder().bucket(bucketName).object(objectName).stream(inputStream, inputStream.available(), -1).contentType("application/octet-stream").build());return bucketName + SLASH + objectName;}@Overridepublic String putObject(String bucketName, MultipartFile file) throws Exception {// 参数校验Assert.notNull(bucketName, "bucketName is not blank");Assert.notNull(file, "file is not null");// 判断存储桶是否存在 不存在则创建createBucket(bucketName);// 文件名String objectName = file.getOriginalFilename();// 上传minioClient.putObject(PutObjectArgs.builder().bucket(bucketName).object(objectName).stream(file.getInputStream(), file.getSize(), -1).contentType(file.getContentType()).build());return bucketName + SLASH + objectName;}@Overridepublic String getObjectURL(String bucketName, String objectName, Integer expires) throws Exception {return minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder().bucket(bucketName).object(objectName).expiry(expires).build());}@Overridepublic InputStream getObject(String bucketName, String objectName) throws Exception {return minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(objectName).build());}@Overridepublic StatObjectResponse getObjectInfo(String bucketName, String objectName) throws Exception {return minioClient.statObject(StatObjectArgs.builder().bucket(bucketName).object(objectName).build());}@Overridepublic void download(String bucketName, String filename, HttpServletResponse response) throws Exception {GetObjectArgs objectArgs = GetObjectArgs.builder().bucket(bucketName).object(filename).build();GetObjectResponse objectResponse = minioClient.getObject(objectArgs);byte[] buf = new byte[1024];int len;try (FastByteArrayOutputStream os = new FastByteArrayOutputStream()) {while ((len = objectResponse.read(buf)) != -1) {os.write(buf, 0, len);}os.flush();byte[] bytes = os.toByteArray();response.setCharacterEncoding("utf-8");response.setContentType("application/force-download");response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");response.addHeader("Content-Disposition", "attachment;fileName=" + filename);try (ServletOutputStream stream = response.getOutputStream()) {stream.write(bytes);stream.flush();}}}@Overridepublic void removeObject(String bucketName, String objectName) throws Exception {minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(objectName).build());}@Overridepublic void removeObjects(String bucketName, List<String> objectNames) throws Exception {List<DeleteObject> deleteObjectList = new ArrayList<>();for (String objectName : objectNames) {DeleteObject deleteObject = new DeleteObject(objectName);deleteObjectList.add(deleteObject);}Iterable<Result<DeleteError>> results = minioClient.removeObjects(RemoveObjectsArgs.builder().bucket(bucketName).objects(deleteObjectList).build());for (Result<DeleteError> result : results) {DeleteError error = result.get();log.error("Error in deleting object " + error.objectName() + "; " + error.message());}}
}
另有启动器版本
点击跳转
相关文章:
SpringBoot集成MinIO8.0
一、安装MinIO 中文官网地址:https://www.minio.org.cn/download.shtml 官网地址:https://min.io/download 官网有相应的安装命令,可查看 建议引用相应版本的依赖 二、集成SpringBoot 1.引入依赖 <dependency><groupId>io.…...
蓝桥等考Python组别五级007
第一部分:选择题 1、Python L5 (15分) 表达式“not a > 0”等价于下面哪个表达式?( ) a < 0a == 0a <= 0a in 0正确答案:C 2、Python L5 (15分) 执行下面的程序,当用键盘输入10时,输出结果是( )。 n &...
【装机】通过快捷键设置BIOS从U盘启动
当要重装系统的时候,是否会遇到一个问题,进入bios的时候就开始凌乱了,因为不懂得怎么用bios设置u盘启动.不要着急,下面来一波小白装机教程 总的来讲,设置电脑从U盘启动一共有两种方法: 第一种:开机时候按快捷键,然后选择U盘启动第…...
关于操作系统与内核科普
关于操作系统与内核科普 一.什么是操作系统 操作系统是管理计算机硬件与软件资源的计算机程序。它为计算机硬件和软件提供了一种中间层。 操作系统是一种软件,主要目的有三种: 一.管理计算机资源,这些资源包括CPU,内存࿰…...
算法练习3——删除有序数组中的重复项
LeetCode 26 删除有序数组中的重复项 给你一个 非严格递增排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。 考虑 nums …...
《YOLOv5:从入门到实战》报错解决 专栏答疑
前言:Hello大家好,我是小哥谈。《YOLOv5:从入门到实战》专栏上线后,部分同学在学习过程中提出了一些问题,笔者相信这些问题其他同学也有可能遇到。为了让大家可以更好地学习本专栏内容,笔者特意推出了该篇专…...
[2023.09.25]:Rust编写基于web_sys的编辑器:输入光标再次定位的小结
前些天,写了探索Rust编写基于web_sys的WebAssembly编辑器:挑战输入光标定位的实践,经过后续的开发检验,我发现了一个问题,就是光标消失了。为了继续输入,用户需要再次使用鼠标点击。现在我已经弄清楚了导致…...
估计、偏差和方差
一、介绍 统计领域为我们提供了很多工具来实现机器学习目标,不仅可以解决训练集上的任务,还可以泛化。基本的概念,例如参数估计、偏差和方差,对于正式地刻画泛化、欠拟合和过拟合都非常有帮助。 二、参数估计 参数估计 是统计学…...
正态分布的概率密度函数|正态分布检验|Q-Q图
正态分布的概率密度函数(Probability Density Function,简称PDF)的函数取值是指在给定的正态分布参数(均值 μ 和标准差 σ)下,对于特定的随机变量取值 x,计算得到的概率密度值 f(x)。这个值表示…...
【接口测试】HTTP协议
一、HTTP 协议基础 HTTP 简介 HTTP 是一个客户端终端(用户)和服务器端(网站)请求和应答的标准(TCP)。通常是由客户端发起一个请求,创建一个到服务器的 TCP 连接,当服务器监听到客户…...
【重新定义matlab强大系列十四】基于问题求解有/无约束非线性优化
🔗 运行环境:Matlab 🚩 撰写作者:左手の明天 🥇 精选专栏:《python》 🔥 推荐专栏:《算法研究》 #### 防伪水印——左手の明天 #### 💗 大家好🤗ᾑ…...
MySQL 索引介绍和最佳实践
目录 一、前言二、索引类型1.1 主键索引(PRIMARY KEY)1.2 唯一索引(UNIQUE)1.3 普通索引(NORMAL)1.3.1 单列普通索引1.3.2 单列前缀普通索引1.3.3 多列普通索引1.3.4 多列前缀普通索引 1.4 空间索引&#x…...
区块链(7):p2p去中心化之初始化websoket服务端
1 整个流程梳理 服务开启onStart()连接打开onOpen()处理接收到的消息onMesage()连接关闭onClose()异常处理onError()2 创建p2p实现类 package com.example.demo.service;import com.example.demo.entity.BlockChain; import org.java_websocket.WebSocket; import org.java_we…...
原型、原型链、判断数据类型
目录 作用 原型链 引用类型:__proto__(隐式原型)属性,属性值是对象函数:prototype(原型)属性,属性值是对象 Function:本身也是函数 相关方法 person.prototype.isPrototypeOf(stu) Object.getPrototypeOf(objec…...
pycharm中配置torch
在控制台cmd中安装好torch后,在pycharm中使用torch,需要进行简单设置即可。 在pycharm中新建一个工程,在file文件中打开setting 在setting中找到project interpreter编译器 找到conda environment的环境配置,设置好相应的目录 新…...
什么是Times New Roman 字体
如何评价 Times New Roman 字体?:https://www.zhihu.com/question/24614549?sortcreated 新罗马字体是Times New Roman字体,是Office Word默认自带的英文字体之一。 中英文字体 写作中,英文和数字的标准字体为 Times New Roma…...
企业会议新闻稿怎么写?会议类新闻稿如何撰写?
企业会议新闻稿是企业对外传递信息的重要途径之一,它能够将企业的决策、动态以及成果展示给公众。本文伯乐网络传媒将详细解析企业会议新闻稿的写作要点和技巧,以及常见问题及解决方法,帮助大家更好地完成企业会议新闻稿的撰写工作。 一、企业…...
算法 滑动窗口最大值-(双指针+队列)
牛客网: BM45 题目: 数组num, 窗口大小size, 所有窗口内的最大值 思路: 用队列作为窗口,窗口内存储数组坐标,left window[0], right从数组0开始遍历完数组,每次新增元素时,(1)先对窗口大小进行收缩到size大小范围,即…...
Java 并发编程面试题——BlockingQueue
目录 1.什么是阻塞队列 (BlockingQueue)?2.BlockingQueue 有哪些核心方法?3.BlockingQueue 有哪些常用的实现类?3.1.ArrayBlockingQueue3.2.DelayQueue3.3.LinkedBlockingQueue3.4.PriorityBlockingQueue3.5.SynchronousQueue 4.✨BlockingQu…...
Ubuntu Nacos开机自启动服务
1、创建service文件 在/lib/systemd/system目录下创建nacos.service文件 [Unit] Descriptionalibaba nacos Afternetwork.target Documentationhttps://nacos.io/zh-cn/[Service] Userroot Grouproot Typeforking Environment"JAVA_HOME/usr/local/programs/jdk-8u333-li…...
【网络】每天掌握一个Linux命令 - iftop
在Linux系统中,iftop是网络管理的得力助手,能实时监控网络流量、连接情况等,帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...
CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型
CVPR 2025 | MIMO:支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题:MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者:Yanyuan Chen, Dexuan Xu, Yu Hu…...
ubuntu搭建nfs服务centos挂载访问
在Ubuntu上设置NFS服务器 在Ubuntu上,你可以使用apt包管理器来安装NFS服务器。打开终端并运行: sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享,例如/shared: sudo mkdir /shared sud…...
Appium+python自动化(十六)- ADB命令
简介 Android 调试桥(adb)是多种用途的工具,该工具可以帮助你你管理设备或模拟器 的状态。 adb ( Android Debug Bridge)是一个通用命令行工具,其允许您与模拟器实例或连接的 Android 设备进行通信。它可为各种设备操作提供便利,如安装和调试…...
MODBUS TCP转CANopen 技术赋能高效协同作业
在现代工业自动化领域,MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步,这两种通讯协议也正在被逐步融合,形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...
python如何将word的doc另存为docx
将 DOCX 文件另存为 DOCX 格式(Python 实现) 在 Python 中,你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是,.doc 是旧的 Word 格式,而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...
c#开发AI模型对话
AI模型 前面已经介绍了一般AI模型本地部署,直接调用现成的模型数据。这里主要讲述讲接口集成到我们自己的程序中使用方式。 微软提供了ML.NET来开发和使用AI模型,但是目前国内可能使用不多,至少实践例子很少看见。开发训练模型就不介绍了&am…...
R语言速释制剂QBD解决方案之三
本文是《Quality by Design for ANDAs: An Example for Immediate-Release Dosage Forms》第一个处方的R语言解决方案。 第一个处方研究评估原料药粒径分布、MCC/Lactose比例、崩解剂用量对制剂CQAs的影响。 第二处方研究用于理解颗粒外加硬脂酸镁和滑石粉对片剂质量和可生产…...
Java求职者面试指南:计算机基础与源码原理深度解析
Java求职者面试指南:计算机基础与源码原理深度解析 第一轮提问:基础概念问题 1. 请解释什么是进程和线程的区别? 面试官:进程是程序的一次执行过程,是系统进行资源分配和调度的基本单位;而线程是进程中的…...
DingDing机器人群消息推送
文章目录 1 新建机器人2 API文档说明3 代码编写 1 新建机器人 点击群设置 下滑到群管理的机器人,点击进入 添加机器人 选择自定义Webhook服务 点击添加 设置安全设置,详见说明文档 成功后,记录Webhook 2 API文档说明 点击设置说明 查看自…...
