SpringBoot 整合 Minio
官网:
MinIO 是一个基于 Go 实现的高性能、兼容 S3 协议的对象存储。它采用 GNU AGPL v3 开源协议,项目地址是 https://github.com/minio/minio 。
它适合存储海量的非结构化的数据,例如说图片、音频、视频等常见文件,备份数据、容器、虚拟机镜像等等,小到 1 KB,大到 5 TB 都可以支持。
添加依赖
<properties><java.version>1.8</java.version><minio.version>8.4.3</minio.version>
</properties><dependencies><dependency><groupId>io.minio</groupId><artifactId>minio</artifactId><version>${minio.version}</version></dependency>
</dependencies>
Minio 配置类
import io.minio.MinioClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class MinioConfig {@Value("${minio.url}")private String url;@Value("${minio.access-key}")private String accessKey;@Value("${minio.secret-key}")private String secretKey;@Beanpublic MinioClient minioClient() {return MinioClient.builder().endpoint(url).credentials(accessKey, secretKey).build();}
}
application.yml 配置文件
minio:url: http://127.0.0.1:9000accessKey: 45wsHpkAIWfhghSs11XsecretKey: D9fghfg6sahgufghfgdOYrwqHqocfgh2njhfgh
MinioTemplate.java 封装方法
封装常用的上传(多文件上传、单文件上传)、获取链接、删除、下载方法,方便使用。
import com.ufan.mall.model.FileVo;
import io.minio.*;
import io.minio.http.Method;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;/*** @ClassName:MinioTemplate.java* @Description:MinioTemplate* @Author:tanyp* @Date:2023/07/27 15:49**/
@Slf4j
@Component
public class MinioTemplate {@Autowiredprivate MinioClient client;/*** @MonthName:upload* @Description: 上传文件* @Author:tanyp* @Date:2023/07/27 15:52* @Param: [file, bucketName]* @return:void**/public FileVo upload(MultipartFile file, String bucketName) {try {createBucket(bucketName);String oldName = file.getOriginalFilename();String fileName = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd")) + UuidUtil.getRandomPwd(15) + oldName.substring(oldName.lastIndexOf("."));client.putObject(PutObjectArgs.builder().bucket(bucketName).object(fileName).stream(file.getInputStream(), file.getSize(), 0).contentType(file.getContentType()).build());String url = this.getObjUrl(bucketName, fileName);return FileVo.builder().oldFileName(oldName).newFileName(fileName).fileUrl(url.substring(0, url.indexOf("?"))).build();} catch (Exception e) {log.error("上传文件出错:{}", e);return null;}}/*** @MonthName:uploads* @Description: 上传多个文件* @Author:tanyp* @Date:2023/07/27 15:52* @Param: [file, bucketName]* @return:void**/public List<FileVo> uploads(List<MultipartFile> files, String bucketName) {try {List<FileVo> list = new ArrayList<>();createBucket(bucketName);for (MultipartFile file : files) {String oldName = file.getOriginalFilename();String fileName = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd")) + UuidUtil.getRandomPwd(15) + oldName.substring(oldName.lastIndexOf("."));client.putObject(PutObjectArgs.builder().bucket(bucketName).object(fileName).stream(file.getInputStream(), file.getSize(), 0).contentType(file.getContentType()).build());String url = this.getObjUrl(bucketName, fileName);list.add(FileVo.builder().oldFileName(oldName).newFileName(fileName).fileUrl(url.substring(0, url.indexOf("?"))).build());}return list;} catch (Exception e) {log.error("上传文件出错:{}", e);return null;}}/*** @MonthName:download* @Description: 下载文件* @Author:tanyp* @Date:2023/07/27 15:54* @Param: [bucketName, fileName]* @return:void**/public void download(String bucketName, String fileName) throws Exception {client.downloadObject(DownloadObjectArgs.builder().bucket(bucketName).filename(fileName).build());}/*** @MonthName:getObjUrl* @Description: 获取文件链接* @Author:tanyp* @Date:2023/07/27 15:55* @Param: [bucketName, fileName]* @return:java.lang.String**/public String getObjUrl(String bucketName, String fileName) throws Exception {return client.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder().bucket(bucketName).object(fileName).method(Method.GET).expiry(30, TimeUnit.SECONDS).build());}/*** @MonthName:delete* @Description: 删除文件* @Author:tanyp* @Date:2023/5/26 15:56* @Param: [bucketName, fileName]* @return:void**/public void delete(String bucketName, String fileName) throws Exception {client.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(fileName).build());}@SneakyThrowspublic void createBucket(String bucketName) {if (!client.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build())) {client.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());String sb = "{\"Version\": \"2012-10-17\",\"Statement\": [{\"Effect\": \"Allow\",\"Principal\": {\"AWS\": [\"*\"]},\"Action\": [\"s3:GetBucketLocation\"],\"Resource\": [\"arn:aws:s3:::" + bucketName + "\"]},{\"Effect\": \"Allow\",\"Principal\": {\"AWS\": [\"*\"]},\"Action\": [\"s3:ListBucket\"],\"Resource\": [\"arn:aws:s3:::" + bucketName + "\"],\"Condition\": {\"StringEquals\": {\"s3:prefix\": [\"*\"]}}},{\"Effect\": \"Allow\",\"Principal\": {\"AWS\": [\"*\"]},\"Action\": [\"s3:GetObject\"],\"Resource\": [\"arn:aws:s3:::" + bucketName + "/**\"]}]}";client.setBucketPolicy(SetBucketPolicyArgs.builder().bucket(bucketName).config(sb).build());}}}
FileVo.java 实体类
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class FileVo {/*** 原文件名*/private String oldFileName;/*** 新文件名*/private String newFileName;/*** 文件路径*/private String fileUrl;}
动态创建 Bucket
如何设置桶的权限?
在MinIO中,可以通过设置桶策略来控制桶的访问权限。桶策略是一个JSON格式的文本文件,用于指定哪些实体(用户、组或IP地址)可以执行哪些操作(读、写、列举等)。
MinIO桶策略的基本结构如下所示:
{"Version": "2012-10-17","Statement": [{"Action": ["action1", "action2", ...],"Effect": "Allow|Deny","Principal": {"AWS": ["arn:aws:iam::account-id:user/user-name"]},"Resource": ["arn:aws:s3:::bucket-name/object-prefix", ...]},...]
}
相关文章:
SpringBoot 整合 Minio
官网: MinIO 是一个基于 Go 实现的高性能、兼容 S3 协议的对象存储。它采用 GNU AGPL v3 开源协议,项目地址是 https://github.com/minio/minio 。 它适合存储海量的非结构化的数据,例如说图片、音频、视频等常见文件,备份数据、…...
《吐血整理》高级系列教程-吃透Fiddler抓包教程(24)-Fiddler如何优雅地在正式和测试环境之间来回切换-中篇
1.简介 在开发或者测试的过程中,由于项目环境比较多,往往需要来来回回地反复切换,那么如何优雅地切换呢?宏哥今天介绍几种方法供小伙伴或者童鞋们进行参考。 2.实际工作场景 2.1问题场景 (1)已发布线上…...
探索 GPTCache|GPT-4 将开启多模态 AI 时代,GPTCache + Milvus 带来省钱秘籍
世界正处于数字化的浪潮中,为了更好理解和分析大量数据,人们对于人工智能(AI)解决方案的需求呈爆炸式增长。 此前,OpenAI 推出基于 GPT-3.5 模型的智能对话机器人 ChatGPT,在自然语言处理(NLP&a…...
纯css实现登录表单动效
效果图: 代码展示 // 我这边用的是elementUI表单校验,更改的样式。 <el-form:model"form":rules"rules"ref"fromList":hide-required-asterisk"true"><el-form-item prop"account"><…...
【css】外边距margin
外边距中有一个属性值比较有意思:inherit 值,继承父类的属性。 <!DOCTYPE html> <html> <head> <style> div {border: 1px solid red;margin-left: 100px; }p.ex1 {margin-left: inherit; } </style> </head> <…...
Cpp8 — 二叉搜索树
二叉搜索树(搜索二叉树、二叉排序树) 二叉搜索树又称二叉排序树,它要么是一棵空树,要么是具有以下性质的二叉树: 1.若它的左子树不为空,则左子树上所有节点的值都小于根节点的值 2.若它的右子树不为空&…...
【实操教程】如何开始用Qt Widgets编程?(一)
Qt 是目前最先进、最完整的跨平台C开发工具。它不仅完全实现了一次编写,所有平台无差别运行,更提供了几乎所有开发过程中需要用到的工具。如今,Qt已被运用于超过70个行业、数千家企业,支持数百万设备及应用。 在本文中࿰…...
openmp和avx配置
实际场景: 项目中数据拷贝慢(使用的是memcpy),希望能加速拷贝,所以尝试了使用avx的流方式,和openmp方式处理 问题1: 调用avx是报错 error: inlining failed in call to always_inline ‘__m512…...
18 个JS优化技巧,可以解决 90% 的屎山代码!!!
文章目录 18 个JS优化技巧,可以解决 90% 的屎山代码!!!1.箭头函数2.解构赋值变量3.使用模版字面量进行字符拼接4.使用展开运算符进行数组和对象操作5.简化循环6.简化判断7.使用对象解构和默认参数简化函数参数8.使用函数式编程概念…...
go逆向符号恢复
前言 之前一直没怎么重视,结果发现每次遇到go的题都是一筹莫展,刷几道题练习一下吧 准备 go语言写的程序一般都被strip去掉符号了,而且ida没有相关的签名文件,没办法完成函数名的识别与字符串的定位,所以第一步通常…...
论文阅读- Uncovering Coordinated Networks on Social Media:Methods and Case Studies
链接:https://arxiv.org/pdf/2001.05658.pdf 目录 摘要: 引言 Methods Case Study 1: Account Handle Sharing Coordination Detection 分析 Case Study 2: Image Coordination Coordination Detection Analysis Case Study 3: Hashtag Sequen…...
应急响应-Linux
应急响应-Linux 1.关键目录 /etc/passwd 记录用户信息 /etc/shadow 保存用户密码(hash) /etc/crontab 定时任务文件 /etc/anacrontab 异步定时任务文件 /etc/rc.d/rc.local 开机启动项 /var/log/btmp …...
利用spinal的伴生对象简化集成rtl代码过程
一 参考 SpinalHDL——集成你的RTL代码 (qq.com)https://mp.weixin.qq.com/s?__biz=Mzg5NjQyMzQwMQ==&mid=2247484852&idx=1&sn=d074279cdc0d58eb5dc73ca68271eee8&chksm=c0000132f77788249838570187495e34cc12ab40e8f8f5ec8f65414ec84b3ece2d17f0d4c4f8&…...
C# Blazor 学习笔记(7):组件嵌套开发
文章目录 前言相关资料组件嵌套组件模板RenderFragment 意义传统前端样式组件化css 前言 我们在组件化一共有三个目的。 不用写CSS不用写html不用写交互逻辑 简单来说就是Java常说的约定大于配置。我们只需要必须的参数即可,其它的都按照默认配置。我们不需要关系…...
DAY1,C高级(命令,Linux的文件系统,软、硬链接文件)
1.创建链接文件; 文件系统中的每个文件都与唯一的 inode 相关联,inode 存储了文件的元数据和数据块的地址,文件名与 inode 之间的链接关系称为硬链接或软链接。 硬链接文件的创建: ln 被链接文件的绝对路径 硬链接文件的绝对…...
Race竞争型漏洞
目录 Race竞争介绍 实验环境配置 安装Cookiecutter 创建基于Django框架的项目 选择配置 创建数据库 加载到环境变量里 数据库的生成 创建一个超级用户(superuser) 启动一个本地开发服务器 配置文件 Race竞争介绍 竞争型漏洞(Race Co…...
基于 FFlogs API 快速实现的 logs 颜色查询小爬虫
文章目录 找到接口解析响应需要平均颜色和过本次数? 找到接口 首先试了一下爬虫,发现和wow一样官网上有暴露的 API,链接在:FFlogs v1 API 文档链接 通过查询官方提供的 API 接口得知: user_name 角色名字 api_key …...
【牛客】统计字符
⭐️ 题目描述 🌟 OJ链接:HJ40 统计字符 ps: 判断字符可以直接使用头文件自带的函数。 函数作用iscntrl判断是否为控制字符isspace判断是否为空白字符(空格、换页’\f’、换行’\n’、回车’\r’、制表符’\t)isdigi…...
测试|Junit相关内容
测试|Junit相关内容 文章目录 测试|Junit相关内容0.Junit说明1.Junit注解TestDisabledBeforeAll和AfterAllBeforeEach和AfterEach 2.Junit参数化单参数多参数(多种/多组)CSV获取参数(支持多种)CSV文件获取参数(支持多种…...
19-2.vuex
目录 1 安装 2 挂载 2.1 vue2写法 2.2 vue3写法 3 state 3.1 声明数据 3.2 使用数据 3.3 处理数据 4 mutations 4.1 基本使用 4.2 传递参数 4.3 mutations中不能写异步的代码 5 actions 5.1 基本使用 5.2 传递参数 6 getters Vuex是做全局数据…...
第19节 Node.js Express 框架
Express 是一个为Node.js设计的web开发框架,它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用,和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...
web vue 项目 Docker化部署
Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段: 构建阶段(Build Stage):…...
Java 语言特性(面试系列1)
一、面向对象编程 1. 封装(Encapsulation) 定义:将数据(属性)和操作数据的方法绑定在一起,通过访问控制符(private、protected、public)隐藏内部实现细节。示例: public …...
MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例
一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...
关于nvm与node.js
1 安装nvm 安装过程中手动修改 nvm的安装路径, 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解,但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后,通常在该文件中会出现以下配置&…...
Python爬虫实战:研究feedparser库相关技术
1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...
Psychopy音频的使用
Psychopy音频的使用 本文主要解决以下问题: 指定音频引擎与设备;播放音频文件 本文所使用的环境: Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...
【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具
第2章 虚拟机性能监控,故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令:jps [options] [hostid] 功能:本地虚拟机进程显示进程ID(与ps相同),可同时显示主类&#x…...
Redis数据倾斜问题解决
Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中,部分节点存储的数据量或访问量远高于其他节点,导致这些节点负载过高,影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...
MySQL用户和授权
开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务: test: # iptables-save | grep 3306 -A mp_srv_whitelist -s 172.16.14.102/32 -p tcp -m tcp --dport 3306 -j ACCEPT -A mp_srv_whitelist -s 172.16.4.16/32 -p tcp -m tcp -…...
