spring boot整合Minio
MinIO
安装MinIo
# 先创建minio 文件存放的位置
mkdir -p /opt/docker/minio/data# 启动并指定端口
docker run \-p 9000:9000 \-p 5001:5001 \--name minio \-v /opt/docker/minio/data:/data \-e "MINIO_ROOT_USER=minioadmin" \-e "MINIO_ROOT_PASSWORD=minioadmin" \-d minio/minio server /data --console-address ":5001"# 设置为和 docker 绑定启动,docker 启动则 minio 就启动
docker update --restart=always
导入依赖
<!-- https://mvnrepository.com/artifact/io.minio/minio -->
<dependency><groupId>io.minio</groupId><artifactId>minio</artifactId><version>8.4.0</version>
</dependency>
application.yml 配置信息
minio:endpoint: http://192.168.218.131/:9000 #Minio服务所在地址bucketName: tulaoda #存储桶名称accessKey: minioadmin #访问的keysecretKey: minioadmin #访问的秘钥
MinioConfig.class配置类
@Data
@Configuration
@ConfigurationProperties(prefix = "minio")
public class MinioConfig {private String endpoint;private String accessKey;private String secretKey;private String bucketName;@Beanpublic MinioClient minioClient() {return MinioClient.builder().endpoint(endpoint).credentials(accessKey, secretKey).build();}
}
minio工具类
@Component
@Slf4j
public class MinioUtil {@Autowiredprivate MinioConfig prop;@Resourceprivate MinioClient minioClient;@Autowiredprivate CodeService codeService;/*** 查看存储bucket是否存在* @return boolean*/public Boolean bucketExists(String bucketName) {Boolean found;try {found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());} catch (Exception e) {e.printStackTrace();return false;}return found;}/*** 创建存储bucket* @return Boolean*/public Boolean makeBucket(String bucketName) {try {minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());} catch (Exception e) {e.printStackTrace();return false;}return true;}/*** 删除存储bucket* @return Boolean*/public Boolean removeBucket(String bucketName) {try {minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());} catch (Exception e) {e.printStackTrace();return false;}return true;}/*** 获取全部bucket*/public List<Bucket> getAllBuckets() {try {List<Bucket> buckets = minioClient.listBuckets();return buckets;} catch (Exception e) {e.printStackTrace();}return null;}/*** 文件上传** @param file 文件* @return Boolean*/public String upload(MultipartFile file) {String originalFilename = file.getOriginalFilename();if (StringUtils.isBlank(originalFilename)){throw new RuntimeException();}String fileName = UuidUtils.generateUuid() + originalFilename.substring(originalFilename.lastIndexOf("."));String objectName = CommUtils.getNowDateLongStr("yyyy-MM/dd") + "/" + fileName;try {PutObjectArgs objectArgs = PutObjectArgs.builder().bucket(prop.getBucketName()).object(objectName).stream(file.getInputStream(), file.getSize(), -1).contentType(file.getContentType()).build();//文件名称相同会覆盖minioClient.putObject(objectArgs);} catch (Exception e) {e.printStackTrace();return null;}return objectName;}/*** 预览图片* @param fileName* @return*/public String preview(String fileName){// 查看文件地址GetPresignedObjectUrlArgs build = new GetPresignedObjectUrlArgs().builder().bucket(prop.getBucketName()).object(fileName).method(Method.GET).build();try {String url = minioClient.getPresignedObjectUrl(build);return url;} catch (Exception e) {e.printStackTrace();}return null;}/*** 文件下载* @param fileName 文件名称* @param res response* @return Boolean*/public void download(String fileName, HttpServletResponse res) {GetObjectArgs objectArgs = GetObjectArgs.builder().bucket(prop.getBucketName()).object(fileName).build();try (GetObjectResponse response = minioClient.getObject(objectArgs)){byte[] buf = new byte[1024];int len;try (FastByteArrayOutputStream os = new FastByteArrayOutputStream()){while ((len=response.read(buf))!=-1){os.write(buf,0,len);}os.flush();byte[] bytes = os.toByteArray();res.setCharacterEncoding("utf-8");// 设置强制下载不打开// res.setContentType("application/force-download");res.addHeader("Content-Disposition", "attachment;fileName=" + fileName);try (ServletOutputStream stream = res.getOutputStream()){stream.write(bytes);stream.flush();}}} catch (Exception e) {e.printStackTrace();}}/*** 查看文件对象* @return 存储bucket内文件对象信息*/public List<Item> listObjects() {Iterable<Result<Item>> results = minioClient.listObjects(ListObjectsArgs.builder().bucket(prop.getBucketName()).build());List<Item> items = new ArrayList<>();try {for (Result<Item> result : results) {items.add(result.get());}} catch (Exception e) {e.printStackTrace();return null;}return items;}/*** 删除* @param fileName* @return* @throws Exception*/public boolean remove(String fileName){try {minioClient.removeObject( RemoveObjectArgs.builder().bucket(prop.getBucketName()).object(fileName).build());}catch (Exception e){return false;}return true;}}
文件处理接口
@Api(tags = "文件相关接口")
@Slf4j
@RestController
@RequestMapping(value = "/product/file")
public class FileController {@Autowiredprivate MinioUtil minioUtil;@Autowiredprivate MinioConfig prop;@ApiOperation(value = "查看存储bucket是否存在")@GetMapping("/bucketExists")public R bucketExists(@RequestParam("bucketName") String bucketName) {return R.ok().put("bucketName",minioUtil.bucketExists(bucketName));}@ApiOperation(value = "创建存储bucket")@GetMapping("/makeBucket")public R makeBucket(String bucketName) {return R.ok().put("bucketName",minioUtil.makeBucket(bucketName));}@ApiOperation(value = "删除存储bucket")@GetMapping("/removeBucket")public R removeBucket(String bucketName) {return R.ok().put("bucketName",minioUtil.removeBucket(bucketName));}@ApiOperation(value = "获取全部bucket")@GetMapping("/getAllBuckets")public R getAllBuckets() {List<Bucket> allBuckets = minioUtil.getAllBuckets();return R.ok().put("allBuckets",allBuckets);}@ApiOperation(value = "文件上传返回url")@PostMapping("/upload")public R upload(@RequestParam("file") MultipartFile file) {String objectName = minioUtil.upload(file);if (null != objectName) {return R.ok().put("url",(prop.getEndpoint() + "/" + prop.getBucketName() + "/" + objectName));}return R.error();}@ApiOperation(value = "图片/视频预览")@GetMapping("/preview")public R preview(@RequestParam("fileName") String fileName) {return R.ok().put("filleName",minioUtil.preview(fileName));}@ApiOperation(value = "文件下载")@GetMapping("/download")public R download(@RequestParam("fileName") String fileName, HttpServletResponse res) {minioUtil.download(fileName,res);return R.ok();}@ApiOperation(value = "删除文件", notes = "根据url地址删除文件")@PostMapping("/delete")public R remove(String url) {String objName = url.substring(url.lastIndexOf(prop.getBucketName()+"/") + prop.getBucketName().length()+1);minioUtil.remove(objName);return R.ok().put("objName",objName);}}
相关文章:
spring boot整合Minio
MinIO 安装MinIo # 先创建minio 文件存放的位置 mkdir -p /opt/docker/minio/data# 启动并指定端口 docker run \-p 9000:9000 \-p 5001:5001 \--name minio \-v /opt/docker/minio/data:/data \-e "MINIO_ROOT_USERminioadmin" \-e "MINIO_ROOT_PASSWORDmini…...

Hadoop----Azkaban的使用与一些报错问题的解决
1.因为官方只放出源码,并没有放出其tar包,所以需要我们自己编译,通过查阅资料我们可以使用gradlew对其进行编译,还是比较简单,然后将里面需要用到的服务文件夹进行拷贝,完善其文件夹结构,通常会…...

「新房家装经验」客厅电视高度标准尺寸及客厅电视机买多大尺寸合适?
客厅电视悬挂高度标准尺寸是多少? 客厅电视悬挂高度通常在90~120厘米之间,电视挂墙高度也可以根据个人的喜好和实际情况来调整,但通常不宜过高,以坐在沙发上观看时眼睛能够平视到电视中心点或者中心稍微往下一点的位置为适宜。 客…...
ArduPilot开源飞控之AP_Baro_DroneCAN
ArduPilot开源飞控之AP_Baro_DroneCAN 1. 源由2. back-end抽象类3. 方法实现3.1 probe3.2 update3.3 subscribe_msgs3.4 handle_pressure/handle_temperature3.5 CAN port 4. 参考资料 1. 源由 鉴于ArduPilot开源飞控之AP_Baro中涉及Sensor Driver有以下总线类型: …...

Supervised Contrastive Pre-training for Mammographic Triage Screening Model
方法 品红色箭头表示将生成的孪生编码器分别迁移到单视角学习模块和双视角学习模块...
JVM技术文档--JVM优化思路以及问题定位--JVM可调整参数汇总
阿丹: 一个优秀的程序员,是因为在线上的排查以及遇到的线上、生产事故较多所以定位问题以及解决问题会比普通程序员快很多,所以一个优秀的程序员要逐渐形成自己的方法论,来完善和解决问题。 我们是如何发现问题的呢? …...
Oracle10g数据库迁移方案
试验了很多次Oracle数据库迁移才成功,贴出来给大家参考一下,我看到有的地方写迁移之后还需要重新建立temp表空间,这个还没有研究。另外说一点的是两个数据库的版本一定要一致,之前失败过一次,就是因为两个数据库的版本…...
备忘录模式:对象状态的保存与恢复
欢迎来到设计模式系列的第十八篇文章,本篇将介绍备忘录模式。备忘录模式是一种行为型设计模式,它允许在不破坏封装性的前提下捕获一个对象的内部状态,并在之后恢复该状态。这种模式通常用于需要提供撤销操作的情况。 什么是备忘录模式&#…...
C# InvokeRequired线程安全
C# InvokeRequired线程安全 为了保证新家的线程可能要对主界面的控件元素的属性发生一些改变,此时防止此操作对于主线程的影响,就提出了 InvokeRequired方法,保证主线程的安全,同时新加的线程也可以改变主页面中元素的值。 定义…...

pdf怎么转成jpg图片格式
pdf怎么转成jpg图片格式?对于大家平时在工作或者生活中的图片使用习惯,经常需要将各种格式的文件转换成易于浏览和使用的JPG格式图片以便保存。如今,因为pdf文件具有更强的稳定性和设备兼容性,PDF文件在平时的电脑使用过程中可以说…...

React +ts + babel+webpack
babel babel/preset-typescript 专门处理ts "babel/cli": "^7.17.6", "babel/core": "^7.17.8", "babel/preset-env": "^7.16.11", "babel/preset-react": "^7.16.7", "babel/preset…...

红队专题-REVERSE二进制逆向反编译
红队专题 招募六边形战士队员IDA pro安装python2加入环境变量py2安装pip安装IDA 7.0 proIDAPython: importing "site" failed. 招募六边形战士队员 一起学习 代码审计、安全开发、web攻防、逆向等。。。 私信联系 IDA pro 安装python2 python-2.7.3.msi 加入环…...
Spring技术原理之Bean生命周期原理解析
Spring技术原理之Bean生命周期原理解析 Spring作为Java领域中的优秀框架,其核心功能之一是依赖注入和生命周期管理。其中,Bean的生命周期管理是Spring框架中一个重要的概念。在本篇文章中,我们将深入探讨Spring技术原理中的Bean生命周期原理…...

Unity实现设计模式——模板方法模式
Unity实现设计模式——模板方法模式 模板模式(Template Pattern), 指在一个抽象类公开定义了执行它的方法的模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。 简单说, 模板方法模式定义一个操作中的算法的骨架&…...
C++实现高性能内存池(二)
文章目录 一、设计内存池二、实现MemoryPool::construct() 实现MemoryPool::deallocate() 实现MemoryPool::~MemoryPool() 实现MemoryPool::allocate() 实现三、与 std::vector 的性能对比一、设计内存池 在上节中,我们在模板链表栈中使用了默认构造器来管理栈操作中的元素内…...

沪深300期权一个点多少钱?
经中国证监会批准,深圳证券交易所于2019年12月23日上市嘉实沪深300ETF期权合约品种。该产品是以沪深300为标的物的嘉实沪深300ETF交易型指数基金为标的衍生的标准化合约,下文介绍沪深300期权一个点多少钱?本文来自:期权酱 一、沪深300期权涨…...

怎么防止重要文件夹丢失?文件夹安全如何保护?
我们在使用电脑的过程中,会将重要数据放在文件夹中,那么,我们该怎么防止重要文件夹丢失呢?下面我们就一起来了解一下。 EFS加密 EFS加密可以对于NTFS卷上的文件夹进行加密,加密后的文件夹将只允许加密时登录系统的用户…...
用于物体识别和跟踪的下游任务自监督学习-1-引言
一:引言: 图像和视频理解是计算机视觉应用中的基本问题,旨在使机器能够像人类一样解释和理解视觉数据。这些问题涉及识别图像和视频中的对象、人物、动作、事件和场景。如图1.1-(a)所示的图像识别任务包括对象检测[1]…...
式子表达ds类——多用位置/值域表示未知数+区间覆盖转区间加:CF407E
https://www.luogu.com.cn/problem/CF407E 多用位置/值域表示未知数 推出的式子中 n n n 表示长度,应该直接换成 r − l 1 r-l1 r−l1 区间覆盖转区间加 推出的式子有 m x , m n mx,mn mx,mn,朴素思路是用单调队列区间覆盖维护 那样就不能很方便…...
Python 实现秒表功能(比较好玩的题目)
以下实例使用 time 模块来实现秒表功能: import time print(按下回车开始计时,按下ctrlc停止计时) while True:input("")starttimetime.time()print(开始)try:while True:print(计时:,round(time.time()-starttime,0),秒)time.sle…...
线程同步:确保多线程程序的安全与高效!
全文目录: 开篇语前序前言第一部分:线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分:synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分ÿ…...

渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止
<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet: https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...
大语言模型如何处理长文本?常用文本分割技术详解
为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...

学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1
每日一言 生活的美好,总是藏在那些你咬牙坚持的日子里。 硬件:OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写,"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...

Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级
在互联网的快速发展中,高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司,近期做出了一个重大技术决策:弃用长期使用的 Nginx,转而采用其内部开发…...

涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战
“🤖手搓TuyaAI语音指令 😍秒变表情包大师,让萌系Otto机器人🔥玩出智能新花样!开整!” 🤖 Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制(TuyaAI…...

NFT模式:数字资产确权与链游经济系统构建
NFT模式:数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新:构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议:基于LayerZero协议实现以太坊、Solana等公链资产互通,通过零知…...

select、poll、epoll 与 Reactor 模式
在高并发网络编程领域,高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表,以及基于它们实现的 Reactor 模式,为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。 一、I…...
Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信
文章目录 Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket(服务端和客户端都要)2. 绑定本地地址和端口&#x…...
C++.OpenGL (20/64)混合(Blending)
混合(Blending) 透明效果核心原理 #mermaid-svg-SWG0UzVfJms7Sm3e {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-icon{fill:#552222;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-text{fill…...