Springboot整合minio组件-分布式文件存储
一、快速开始
Minlo说明:
- Minio是Apcche旗下的一款开源的轻量级文件服务器,基于对象存储,协议是基于Apache License v2.0,开源可用于商务。
- Minio主要用来存储非结构化的数据,类似文件,图片,照片,日志文件,各类备份文件等,按照官网描述,文件的大小从几KB到5TB。
- Minio提供了非常方便,友好的界面,并且文档也是非常丰富,具体可以参考它的文档:https://docs.min.io/cn/
- Minlo作用类似于FastDFS和阿里云的OSS进行对象存储
- 安装minlo服务器参考:https://blog.csdn.net/u010189683/article/details/108171562
1、添加依赖
<!--minio方案-->
<dependency><groupId>io.minio</groupId><artifactId>minio</artifactId><version>7.0.2</version>
</dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId><optional>true</optional>
</dependency>
2、添加配置项
## minio配置
minio:endpoint: http://192.168.179.131:9000/accessKey: adminsecretKey: admin123456
3、配置项和工具类
@Data
@Configuration
@ConfigurationProperties(prefix = "minio")
public class MinioConfig {private String endpoint;private String accessKey;private String secretKey;@Beanpublic MinioClient getMinioClient() throws InvalidEndpointException, InvalidPortException {MinioClient minioClient = new MinioClient(endpoint, accessKey, secretKey);return minioClient;}}
@Component
public class MinioUtil {@Value("${minio.endpoint}")private String endpoint;@Value("${minio.accessKey}")private String accessKey;@Value("${minio.secretKey}")private String secretKey;private static final int DEFAULT_EXPIRY_TIME = 7 * 24 * 3600;private static MinioClient minioClient;@Autowired@SneakyThrowspublic MinioClient setMinioClient(){MinioClient minioClient = new MinioClient(endpoint, accessKey, secretKey);return minioClient;}/*** 检查存储桶是否存在*/@SneakyThrowspublic boolean bucketExists(String bucketName){boolean flag = minioClient.bucketExists(bucketName);return flag ? true : false;}/*** 创建存储桶*/@SneakyThrowspublic boolean makeBucket(String bucketName) {boolean flag = bucketExists(bucketName);if(flag) return false;minioClient.makeBucket(bucketName);return true;}/*** 列出所有存储桶名称*/@SneakyThrowspublic List<String> listBucketNames() {List<Bucket> bucketList = listBuckets();return bucketList.stream().map(item->bucket.name()).collect(Collector.toList())}/*** 列出所有存储桶*/@SneakyThrowspublic List<Bucket> listBuckets() {return minioClient.listBuckets();}/*** 删除存储桶*/@SneakyThrowspublic boolean removeBucket(String bucketName) {boolean flag = bucketExists(bucketName);if(flag) return false;Iterable<Result<Item>> myObjects = listObjects(bucketName);for (Result<Item> result : myObjects) {Item item = result.get();// 有对象文件,则删除失败if (item.size() > 0) {return false;}}// 删除存储桶,注意,只有存储桶为空时才能删除成功。minioClient.removeBucket(bucketName);flag = bucketExists(bucketName);if (!flag) {return true;}}/*** 列出存储桶中的所有对象名称*/@SneakyThrowspublic List<String> listObjectNames(String bucketName) {List<String> listObjectNames = new ArrayList<>();boolean flag = bucketExists(bucketName);if (flag) {Iterable<Result<Item>> myObjects = listObjects(bucketName);for (Result<Item> result : myObjects) {Item item = result.get();listObjectNames.add(item.objectName());}}return listObjectNames;}/*** 列出存储桶中的所有对象*/@SneakyThrowspublic Iterable<Result<Item>> listObjects(String bucketName) {boolean flag = bucketExists(bucketName);return flag?minioClient.listObjects(bucketName):null;}/*** 通过文件上传到对象*/@SneakyThrowspublic boolean putObject(String bucketName, String objectName, String fileName){boolean flag = bucketExists(bucketName);if (flag) {minioClient.putObject(bucketName, objectName, fileName, null);ObjectStat statObject = statObject(bucketName, objectName);if (statObject != null && statObject.length() > 0) {return true;}}return false;}/*** 通过InputStream上传对象*/@SneakyThrowspublic boolean putObject(String bucketName, String objectName, InputStream stream) {boolean flag = bucketExists(bucketName);if (flag) {minioClient.putObject(bucketName, objectName, stream, new PutObjectOptions(stream.available(), -1));ObjectStat statObject = statObject(bucketName, objectName);if (statObject != null && statObject.length() > 0) {return true;}}return false;}/*** 以流的形式获取一个文件对象*/@SneakyThrowspublic InputStream getObject(String bucketName, String objectName){boolean flag = bucketExists(bucketName);if (flag) {ObjectStat statObject = statObject(bucketName, objectName);if (statObject != null && statObject.length() > 0) {InputStream stream = minioClient.getObject(bucketName, objectName);return stream;}}return null;}/*** 以流的形式获取一个文件对象(断点下载)*/@SneakyThrowspublic InputStream getObject(String bucketName, String objectName, long offset, Long length){boolean flag = bucketExists(bucketName);if (flag) {ObjectStat statObject = statObject(bucketName, objectName);if (statObject != null && statObject.length() > 0) {InputStream stream = minioClient.getObject(bucketName, objectName, offset, length);return stream;}}return null;}/*** 下载并将文件保存到本地*/@SneakyThrowspublic boolean getObject(String bucketName, String objectName, String fileName) {boolean flag = bucketExists(bucketName);if (flag) {ObjectStat statObject = statObject(bucketName, objectName);if (statObject != null && statObject.length() > 0) {minioClient.getObject(bucketName, objectName, fileName);return true;}}return false;}/*** 删除一个对象*/@SneakyThrowspublic boolean removeObject(String bucketName, String objectName) {boolean flag = bucketExists(bucketName);if (flag) {minioClient.removeObject(bucketName, objectName);return true;}return false;}/*** 删除指定桶的多个文件对象,返回删除错误的对象列表,全部删除成功,返回空列表*/@SneakyThrowspublic List<String> removeObject(String bucketName, List<String> objectNames){List<String> deleteErrorNames = new ArrayList<>();boolean flag = bucketExists(bucketName);if (flag) {Iterable<Result<DeleteError>> results = minioClient.removeObjects(bucketName, objectNames);for (Result<DeleteError> result : results) {DeleteError error = result.get();deleteErrorNames.add(error.objectName());}}return deleteErrorNames;}/*** 生成一个给HTTP GET请求用的presigned URL。* 浏览器/移动端的客户端可以用这个URL进行下载,即使其所在的存储桶是私有的。这个presigned URL可以设置一个失效时间,默认值是7天。*/@SneakyThrowspublic String presignedGetObject(String bucketName, String objectName, Integer expires) {boolean flag = bucketExists(bucketName);return bucketExists(bucketName) ? minioClient.presignedGetObject(bucketName, objectName, expires):null;}/*** 生成一个给HTTP PUT请求用的presigned URL。* 浏览器/移动端的客户端可以用这个URL进行上传,即使其所在的存储桶是私有的。这个presigned URL可以设置一个失效时间,默认值是7天。*/@SneakyThrowspublic String presignedPutObject(String bucketName, String objectName, Integer expires) {return bucketExists(bucketName) ? minioClient.presignedPutObject(bucketName, objectName, expires):null;}/*** 获取对象的元数据*/@SneakyThrowspublic ObjectStat statObject(String bucketName, String objectName){return bucketExists(bucketName) ? minioClient.statObject(bucketName, objectName) : null;}/*** 文件访问路径*/@SneakyThrowspublic String getObjectUrl(String bucketName, String objectName) {return bucketExists(bucketName) ? minioClient.getObjectUrl(bucketName, objectName) : "";}
}
相关文章:
Springboot整合minio组件-分布式文件存储
一、快速开始 Minlo说明: Minio是Apcche旗下的一款开源的轻量级文件服务器,基于对象存储,协议是基于Apache License v2.0,开源可用于商务。Minio主要用来存储非结构化的数据,类似文件,图片,照…...
多态/虚函数/虚函数表
OVERVIEW 多态/虚函数/虚函数表1.虚函数引入后类发生的变化?2.虚函数表的生成时机和生成原因?3.虚函数表指针赋值的时机?4.类对象在内存中的布局?5.虚函数的工作原理和多态性的体现?6.其他问题 多态/虚函数/虚函数表 n…...
QT中按钮的基类QAbstractButton
QT中按钮的基类QAbstractButton 关于控件类的学习方法继承关系信号槽函数标题和图标按钮的 Check 属性 关于控件类的学习方法 控件类很多,API更多,但是不需要记忆知道控件对应的类名,通过帮助文档随用随查优先看帮助文档中控件对应的信号和槽…...
并查集(种类并查集,带权并查集)
链接:登录—专业IT笔试面试备考平台_牛客网 来源:牛客网 题目描述 动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形。A吃B,B吃C,C吃A。 现有N个动物,以1-N编号。每个动物都…...
飞天使-k8s基础组件分析-控制器
文章目录 控制器含义解释pod的标签与注释ReplicaControllerReplicaSetDeploymentsDaemonSetJobCronjob参考文档 控制器含义解释 空调遥控器知道吧ReplicationController: ReplicationController确保在任何时候都运行指定数量的pod副本。换句话说,一个ReplicationCo…...
有序充电运营管理平台是基于物联网和大数据技术的充电设施管理系统-安科瑞黄安南
随着我国能源战略发展以及低碳行动的实施,电动汽车已逐步广泛应用,而电动汽车的应用非常符合当今社会对环保意识的要求,以及有效节省化石燃料的消耗。 由于其没有污染排放的优点以及政府部门的关注,电动汽车将成为以后出行的重要…...
LeetCode-227-基本计算器Ⅱ
题目描述: 给你一个字符串表达式 s ,请你实现一个基本计算器来计算并返回它的值。 整数除法仅保留整数部分。 你可以假设给定的表达式总是有效的。所有中间结果将在 [-231, 231 - 1] 的范围内。 注意:不允许使用任何将字符串作为数学表达式计…...
dart 学习列表 List
List 列表 在 Dart 编程语言中,List 是一种有序的集合数据类型,用于存储一系列项目。它允许您在单个变量中存储多个项目,并提供了许多操作来管理列表中的数据。以下是关于 Dart 中的 List 的一些重要信息: 创建 List: …...
数据结构--树4.2.1(二叉树)
目录 一、二叉树的存储结构 二、二叉树的遍历 一、二叉树的存储结构 顺序存储结构:二叉树的顺序存储结构就是用一维数组存储二叉树中的各个结点,并且结点的存储位置能体现结点之间的逻辑关系。 链式存储结构:二叉树每个结点最多只有两个孩…...
Presto之Driver个数
一. 前言 在Presto的Stage Performace中,每个Operator中都会有Driver个数的显示,如下图所示。本文主要介绍Presto中是如何决定Driver的个数的。 二. Driver个数 在Presto中,一个pipeline中启动多少个Driver,是由此Pipeline处理的S…...
R语言响应面(RSM)、线性模型lm分析生产过程影响因素可视化
全文链接:https://tecdat.cn/?p33499 响应面(Response Surface Methodology,RSM)分析是一种常用的统计方法,用于研究和优化生产过程中的影响因素。通过建立数学模型来描述因素与响应之间的关系,RSM可以帮助…...
剑指Offer --- 字符串篇
剑指Offer — 字符串篇 — 剑指的题解K神已经写的已经非常详细了,并且Github上开源的电子书目前热度也非常高,这个12天12个模块系列就当作自己的秋招刷题汇总了,欢迎大家交流。 剑指 Offer 05. 替换空格 思路 **(线性扫描) ** O(n) 这个…...
7.elasticsearch同步工具-logstah
1.logstah Logstash 是一个用于数据处理和转换的开源工具,它可以将来自不同源头的数据收集、转换、过滤,并将其发送到不同的目标。Logstash 是 ELK(Elasticsearch、Logstash 和 Kibana)技术栈的一部分,通常与 Elastics…...
Redis之stream类型解读
目录 基本介绍 数据结构 消息 消费组 消费者 基本使用命令 概述 xadd 命令 xtrim 命令 xdel 命令 xlen 命令 xrange 命令 xread 命令 xgroup 命令 xreadgroup 命令 xack 命令 基本介绍 Redis stream(流)是一种数据结构,其…...
C++ 网络编程项目fastDFS分布式文件系统(九)总结
1. Location语法 1. 语法规则 location [ |~|~ * |^~ ] /uri/ { … } 正则表达式中的特殊字符 : - . () {} [] * ? 2. Location 优先级说明 在 nginx 的 location 和配置中 location 的顺序没有太大关系。 与 location 表达式的类型有关。 相同类型的表达式&a…...
第五章 树与二叉树 一、树的定义与考点
一、定义 1.树是由n (n > 0) 个节点组成的有限集合。 2.当n0时,称为空树。 3.在非空树中,有且仅有一个节点没有前驱,其他节点都有且仅有一个前驱,称为根节点。 4.每个节点有零个或多个子节点,而每个子节点又有零…...
C语言基础之——指针(下)
前言:本篇文章将继续讲解有关指针的剩余基础知识。 学无止境,一起加油叭!! 目录 一.指针运算 1.指针 - 整数 2.指针的关系运算 3.指针 - 指针 二.指针与数组 三.二级指针 四.指针数组 总结 一.指针运算 指针运算包括以下三…...
小研究 - JVM 的类装载机制
本文通过对一个类装载实例的分析,阐明了 Java虚拟机的类装载的代理机制和由此定义的命名空间,指出了类装载机制在容器/组件/抽象框架结构中的作用。 目录 1 引言 2 实例 3 分析 3.1 类装载的代理机制 3.2 Java的命名空间 3.3 解决问题 4 应…...
项目---日志系统
目录 项目系统开发环境核心技术日志系统介绍为什么需要日志系统? 日志系统框架设计日志系统模块划分代码实现通用工具实现日志等级模块实现日志消息模块实现格式化模块实现落地模块实现日志器模块同步日志器异步日志器缓冲区实现异步工作器实现 回归异步日志器模块建造者模式日…...
设计模式--建造者模式(Builder Pattern)
一、什么是建造者模式 建造者模式(Builder Pattern)是一种创建型设计模式,它关注如何按照一定的步骤和规则创建复杂对象。建造者模式的主要目的是将一个复杂对象的构建过程与其表示分离,从而使同样的构建过程可以创建不同的表示。…...
【仅限核心开发者知晓】Polars 2.0清洗Pipeline的4层IR抽象:为何比Pandas快11.8倍?源码注释级解读
第一章:Polars 2.0清洗Pipeline的演进本质与性能跃迁全景Polars 2.0 将清洗 Pipeline 从“惰性执行显式优化提示”升级为“全图级自动重写零拷贝流式调度”,其本质是将数据清洗从过程式编排转向声明式语义图推理。核心突破在于 LazyFrame 的物理计划生成…...
从Buck电路到PCB布局:DCDC带载异常的硬件设计避坑手册
从Buck电路到PCB布局:DCDC带载异常的硬件设计避坑手册 在电源设计领域,Buck电路因其高效、紧凑的特性成为各类电子设备的首选方案。然而,许多工程师在初次接触DCDC转换器设计时,常常会遇到一个令人困惑的现象:空载测试…...
倩女幽魂易语言源码|支持编译运行,适合易语言开发者学习研究
温馨提示:文末有联系方式【标一】可编译倩女幽魂易语言源码开放 本套源码基于易语言开发,已完成基础环境配置与编译测试,生成的程序可正常启动并执行核心逻辑。 适用于熟悉易语言语法、掌握API调用与内存读写技术的开发者。【标二】仅面向具备…...
如何高效抓取足球数据:SoccerData实战指南
如何高效抓取足球数据:SoccerData实战指南 【免费下载链接】soccerdata ⛏⚽ Scrape soccer data from Club Elo, ESPN, FBref, FiveThirtyEight, Football-Data.co.uk, SoFIFA and WhoScored. 项目地址: https://gitcode.com/gh_mirrors/so/soccerdata 在足…...
P1061 Jam 的计数法【洛谷算法习题】
P1061 Jam 的计数法 网页链接 P1061 Jam 的计数法 题目描述 Jam 是个喜欢标新立异的科学怪人。他不使用阿拉伯数字计数,而是使用小写英文字母计数,他觉得这样做,会使世界更加丰富多彩。 在他的计数法中,每个数字的位数都是相…...
新中大SE系统反月结避坑指南:从月结修复到重新记账的完整操作解析
新中大SE系统月结异常处理实战手册:从错误回溯到数据修正的全流程精解 财务系统的月结操作如同会计周期的"收官之战",一旦发现历史凭证存在错误,往往让使用者陷入两难境地——既要确保数据准确性,又担心操作不当引发连锁…...
数据库字段ip地址varbinary、inet6_aton()、inet6_ntoa()等
文章目录准备数据inet6_aton()、 inet6_ntoa()其他函数为什么ip地址要用varbinary(16)?其他文档这里主要说下mysql的varbinary字段类型。准备数据 CREATE TABLE user_logs (id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,ip VARBINARY(16) NOT NULL COMMENT 存储IPv4/IPv6地…...
逆向分析实战:从IDA反编译看bjdctf_2020_babystack的栈溢出漏洞成因与利用
逆向工程实战:bjdctf_2020_babystack栈溢出漏洞的深度解析 在二进制安全领域,栈溢出漏洞始终是攻防对抗的经典课题。今天我们将以bjdctf_2020_babystack这道CTF题目为案例,通过IDA Pro的静态分析视角,完整还原从漏洞发现到利用的…...
从零到一:彻底搞懂Anaconda,打造完美的Python开发环境
别再为Python环境搞得焦头烂额了,这篇教程带你一次性解决所有烦恼。 作为Python开发者,你是否曾经遇到过这样的场景:项目A需要Python 3.6和旧版本的TensorFlow,而项目B却要求Python 3.12和最新的PyTorch。如果只在系统里装一个Pyt…...
如何零门槛拥有专属AI数字人?Duix.Avatar全流程实践指南
如何零门槛拥有专属AI数字人?Duix.Avatar全流程实践指南 【免费下载链接】Duix-Avatar 项目地址: https://gitcode.com/GitHub_Trending/he/Duix-Avatar 想制作个人数字分身却被技术门槛劝退?每月花费数千元购买商业数字人服务让你望而却步&…...
