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…...
TDengine 快速体验(Docker 镜像方式)
简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能,本节首先介绍如何通过 Docker 快速体验 TDengine,然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker,请使用 安装包的方式快…...
YSYX学习记录(八)
C语言,练习0: 先创建一个文件夹,我用的是物理机: 安装build-essential 练习1: 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件,随机修改或删除一部分,之后…...
django filter 统计数量 按属性去重
在Django中,如果你想要根据某个属性对查询集进行去重并统计数量,你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求: 方法1:使用annotate()和Count 假设你有一个模型Item,并且你想…...
OPENCV形态学基础之二腐蚀
一.腐蚀的原理 (图1) 数学表达式:dst(x,y) erode(src(x,y)) min(x,y)src(xx,yy) 腐蚀也是图像形态学的基本功能之一,腐蚀跟膨胀属于反向操作,膨胀是把图像图像变大,而腐蚀就是把图像变小。腐蚀后的图像变小变暗淡。 腐蚀…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...
python爬虫——气象数据爬取
一、导入库与全局配置 python 运行 import json import datetime import time import requests from sqlalchemy import create_engine import csv import pandas as pd作用: 引入数据解析、网络请求、时间处理、数据库操作等所需库。requests:发送 …...
PH热榜 | 2025-06-08
1. Thiings 标语:一套超过1900个免费AI生成的3D图标集合 介绍:Thiings是一个不断扩展的免费AI生成3D图标库,目前已有超过1900个图标。你可以按照主题浏览,生成自己的图标,或者下载整个图标集。所有图标都可以在个人或…...
CSS 工具对比:UnoCSS vs Tailwind CSS,谁是你的菜?
在现代前端开发中,Utility-First (功能优先) CSS 框架已经成为主流。其中,Tailwind CSS 无疑是市场的领导者和标杆。然而,一个名为 UnoCSS 的新星正以其惊人的性能和极致的灵活性迅速崛起。 这篇文章将深入探讨这两款工具的核心理念、技术差…...
开疆智能Ethernet/IP转Modbus网关连接鸣志步进电机驱动器配置案例
在工业自动化控制系统中,常常会遇到不同品牌和通信协议的设备需要协同工作的情况。本案例中,客户现场采用了 罗克韦尔PLC,但需要控制的变频器仅支持 ModbusRTU 协议。为了实现PLC 对变频器的有效控制与监控,引入了开疆智能Etherne…...
Spring Boot 中实现 HTTPS 加密通信及常见问题排查指南
Spring Boot 中实现 HTTPS 加密通信及常见问题排查指南 在金融行业安全审计中,未启用HTTPS的Web应用被列为高危漏洞。通过正确配置HTTPS,可将中间人攻击风险降低98%——本文将全面解析Spring Boot中HTTPS的实现方案与实战避坑指南。 一、HTTPS 核心原理与…...
