MinIO的预签名直传机制
我们传统使用MinIo做OSS对象存储的应用方式往往都是在后端配置与MinIO的连接和文件上传下载的相关接口,然后我们在前端调用这些接口完成文件的上传下载机制,但是,当并发量过大,频繁访问会对后端的并发往往会对服务器造成极大的压力,大文件传输场景下,服务器被迫承担数据中转的角色,既消耗大量带宽资源,又形成单点性能瓶颈。这时,我们引入了MinIO的一种预签名机制。
预签名机制:在后端对文件的上传和下载操作生成一个URL,前端针对不同的文件操作形式请求会获取到对应的URL,这个URL可以理解为一个临时的通行证,有了这个URL后,前端可以直接向MinIO的服务端发上传和下载的相应请求,与MinIO直连操作,大大减缓了对后端服务器的压力
1.后端配置
1.1 引入Maven依赖并配置MinIO
<!--minio--> <dependency><groupId>io.minio</groupId><artifactId>minio</artifactId> </dependency>
/** MinIO配置类* @Author GuihaoLv*/ @Configuration @EnableConfigurationProperties(MinIoProperties.class) public class MinIoConfiguration {@Autowiredprivate MinIoProperties properties;@Beanpublic MinioClient minioClient() {return MinioClient.builder().endpoint(properties.getEndpoint()).credentials(properties.getAccessKey(), properties.getSecretKey()).build();}}
1.2 生成预签名接口封装:
/**要改成使用预签名URL,让前端直接与MinIO交互,减轻服务器负担。* 生成上传预签名URL(PUT)* @param fileName* @return*/ @GetMapping("/presigned-upload-url") @ApiOperation("获取上传预签名URL") public Result<String> generateUploadUrl(@RequestParam("fileName") String fileName) {System.out.println("测试"+fileName);String url = commonFileService.generatePresignedUploadUrl(fileName);System.out.println("结构"+url);return Result.success(url); }/**要改成使用预签名URL,让前端直接与MinIO交互,减轻服务器负担。* 生成下载预签名URL(GET)* @param fileName* @return*/ @GetMapping("/presigned-download-url") @ApiOperation("获取下载预签名URL") public Result<String> generateDownloadUrl(@RequestParam("fileName") String fileName) {String url = commonFileService.generatePresignedDownloadUrl(fileName);return Result.success(url); }
/**生成上传预签名URL(PUT)* @param fileName* @return*/ public String generatePresignedUploadUrl(String fileName) {try {// 安全处理文件名(防止路径遍历)String safeFileName = sanitizeFileName(fileName);// 生成预签名URL(PUT方法)return client.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder().method(Method.PUT).bucket(properties.getBucketName()).object(safeFileName).expiry(15, TimeUnit.MINUTES) // 15分钟有效.build());} catch (Exception e) {throw new RuntimeException("生成预签名URL失败", e);} }/*** 生成下载预签名URL(GET)* @param fileName* @return*/ public String generatePresignedDownloadUrl(String fileName) {try {String safeFileName = sanitizeFileName(fileName);return client.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder().method(Method.GET).bucket(properties.getBucketName()).object(safeFileName).expiry(1, TimeUnit.HOURS) // 1小时有效.build());} catch (Exception e) {throw new RuntimeException("生成预签名URL失败", e);} }// 文件名安全处理 private String sanitizeFileName(String fileName) {// 过滤非法字符,防止路径遍历return fileName.replaceAll("[^a-zA-Z0-9-_.]", ""); }
1.3 前端封装获取预签名和直连MinIO做上传下载的请求
// 获取上传预签名URL export const getPresignedUploadUrl = (fileName) => {return httpInstance({url: '/web/commonFile/presigned-upload-url',method: 'GET',params: { fileName },}); };// 获取下载预签名URL export const getPresignedDownloadUrl = (fileName) => {return httpInstance({url: '/web/commonFile/presigned-download-url',method: 'GET',params: { fileName },}); };// 单个文件直传MinIO,上传文件 export const uploadViaPresignedUrl = async (file: File) => {try {// 步骤1: 获取未编码的原始文件名(需与后端生成的签名匹配)const rawFileName = file.name;// 步骤2: 调用后端接口获取预签名URL(必须传递原始文件名)const res=await getPresignedUploadUrl(rawFileName);const presignedUrl=res.data;// 调试输出:验证URL格式console.log('[DEBUG] 预签名URL:', presignedUrl); // 应输出类似 http://47.99.49.193:9000/...// 步骤3: 直接向MinIO发送PUT请求(绕过代理)const response = await axios.put(presignedUrl, file, {// 关键配置:禁用代理和默认请求头baseURL: '', // [!code ++] 清除默认baseURLheaders: {'Content-Type': 'application/octet-stream' // MinIO通用类型}});return response.data;} catch (error) {throw new Error(`上传失败: ${(error).response?.data || error.message}`);} };// 使用预签名URL直连MinIO下载文件 export const downloadViaPresignedUrl = async (fileName) => {try {// 1. 获取预签名URL:调用后端接口生成临时有效的下载URLconst { data: { data: presignedUrl } } = await getPresignedDownloadUrl(fileName);// 2. 创建隐藏链接触发下载const link = document.createElement('a');link.href = presignedUrl; // 设置URLlink.download = fileName; // 设置下载文件名,需与 MinIO 存储的文件名一致。document.body.appendChild(link); // 将链接添加到DOMlink.click(); // 模拟点击触发下载document.body.removeChild(link); // 移除临时链接return true; // 表示下载已触发} catch (error) {throw new Error('下载失败: ' + error.message); // 统一错误处理} };
1.4:写一个前端页面测试前端直连MinIO的功能实现
<script setup lang="ts"> import { ref } from 'vue'; import {uploadViaPresignedUrl,downloadViaPresignedUrl } from '@/api/file';// 定义响应式变量 const selectedFile = ref<File | null>(null); // 存储用户选择的文件 const downloadFileName = ref<string>(''); // 下载时输入的文件名 const uploadStatus = ref<string>(''); // 上传状态提示 const downloadStatus = ref<string>(''); // 下载状态提示// 处理文件选择事件 const handleFileChange = (event: Event) => {const target = event.target as HTMLInputElement;if (target.files && target.files.length > 0) {selectedFile.value = target.files[0];uploadStatus.value = ''; // 重置上传状态} };// 上传文件到MinIO const uploadFile = async () => {uploadStatus.value = '上传中...';await uploadViaPresignedUrl(selectedFile.value);uploadStatus.value = '上传成功!';selectedFile.value = null; // 清空文件选择 }// 下载文件从MinIO const downloadFile = async () => {downloadStatus.value = '正在触发下载...';const success = await downloadViaPresignedUrl(downloadFileName.value);if (success) {downloadStatus.value = '下载已触发!';}}; </script><template><div class="container"><!-- 上传文件部分 --><h2>测试MinIO文件上传</h2><input type="file" @change="handleFileChange" /><button @click="uploadFile" :disabled="!selectedFile">上传</button><p>{{ uploadStatus }}</p><!-- 下载文件部分 --><h2>测试MinIO文件下载</h2><inputv-model="downloadFileName"type="text"placeholder="请输入文件名(如 test.jpg)"/><button @click="downloadFile">下载</button><p>{{ downloadStatus }}</p></div> </template>
上传测试结果:
下载测试:
相关文章:
MinIO的预签名直传机制
我们传统使用MinIo做OSS对象存储的应用方式往往都是在后端配置与MinIO的连接和文件上传下载的相关接口,然后我们在前端调用这些接口完成文件的上传下载机制,但是,当并发量过大,频繁访问会对后端的并发往往会对服务器造成极大的压力…...
树莓科技集团董事长:第五代产业园运营模式的深度剖析与展望
第五代产业园运营模式,以创新为核心驱动,强调数字化、网络化和资源整合。树莓科技集团在这一领域具有代表性,其运营模式值得深入剖析。 核心特征 数字化转型:第五代产业园高度重视数字化技术的应用,通过构建数字化平…...
项目组织管理类型-职能式组织和矩阵式组织的区别
在职能式组织和矩阵式组织中,任务分配和人员安排确实有显著的不同,让我们通过以下例子来进一步解释: 职能式组织在职能式组织中,任务通常是根据部门的职能进行下达的。 例如,一家制造公司的组织结构如下: …...
树莓科技(成都)集团:如何铸就第五代产业园标杆
树莓科技(成都)集团铸就第五代产业园标杆,主要体现在以下几个方面: 精准定位与前瞻布局 树莓科技并非盲目扩张,而是精准锚定数字经济发展方向。以成都为起点,迅速构建起全国性的园区版图,体现…...
【Quest开发】手柄交互震动
软件:Unity 2022.3.51f1c1、vscode、Meta XR All in One SDK V72(要提前导入哦) 硬件:Meta Quest3 参考Meta开发文档:https://developers.meta.com/horizon/documentation/unity/unity-haptics-sdk-integrate 这篇官…...
《Transformer如何进行图像分类:从新手到入门》
引言 如果你对人工智能(AI)或深度学习(Deep Learning)感兴趣,可能听说过“Transformer”这个词。它最初在自然语言处理(NLP)领域大放异彩,比如在翻译、聊天机器人和文本生成中表现出…...
数字图像处理与Python语言实现-Box模糊CUDA实现
Box模糊CUDA实现 文章目录 Box模糊CUDA实现1、Box模糊的基本原理2、算法优化:滑动窗口技术3、参数对模糊效果的影响4、Box模糊的优缺点5、与高斯模糊的对比6、实际应用场景7、算法实现7.1 PyCUDA实现7.2 CuPy实现7.3 C++与CUDA实现8、总结在图像处理领域,**Box模糊(方框模糊…...
MAVEN解决版本依赖冲突
文章目录 一、依赖冲突概念1、什么是依赖冲突2、依赖冲突的原因3、如何解决依赖冲突 二、查看依赖冲突-maven-helper1、安装2、helper使用1、conflicts的阅读顺序(从下向上看)2、dependencies as List的阅读顺序(从下向上看)3、de…...
Compose 实践与探索五 —— AnimationSpec
不论是 animateXxxAsState() 还是 Animatable 的 animateTo() 都可以传入 AnimationSpec 以配置动画的规格: Composable fun animateDpAsState(targetValue: Dp,animationSpec: AnimationSpec<Dp> dpDefaultSpring,label: String "DpAnimation",…...
Embedding模型到底是什么?
嵌入模型(Embedding Model)是一种将高维数据映射到低维空间的工具,广泛应用于自然语言处理(NLP)、推荐系统和图像识别等领域。它的核心目标是将复杂的数据(如文本、图像或用户行为)转换为稠密的…...
数据结构(一)——绪论
一、数据结构的研究内容 1.数据的各种逻辑结构和物理结构,以及他们之间的相应关系 2.存储结构的方法,对每种结构定义相适应的各种运算 3.设计出相应的算法 4.分析算法的效率 二、数据结构的基本概念 1.数据(data):…...
VMware虚拟机网络连接模式介绍以及nat模式访问公网实践
在 VMware 虚拟机中,网络配置是非常重要的一部分。VMware 提供了三种主要的网络连接模式,分别是桥接模式(Bridged)、NAT模式(NAT) 和仅主机模式(Host-Only)。每种模式都有其特定的用…...
Selenium Manager和webdriver manager的区别与联系
一、引言 1.1 自动化测试的重要性 在现代软件开发流程中,自动化测试已经成为保证软件质量和提高交付效率的关键实践。随着软件开发周期的缩短和软件复杂性的增加,手工测试已无法满足快速迭代的需求。自动化测试能够快速、准确地执行重复性测试任务&…...
八叉树地图的原理与实现
八叉树与体素图 八叉树地图 八叉树地图是可变分辨率的三维栅格地图,可以自由调整分辨率,如下所示: 根据点云的数量或密度决定每个叶子方块是否被占据 体素图 体素就是固定分辨率的三维栅格地图,如下所示: 根据点云…...
DeepSeek模型本地化部署方案及Python实现
DeepSeek实在是太火了,虽然经过扩容和调整,但反应依旧不稳定,甚至小圆圈转半天最后却提示“服务器繁忙,请稍后再试。” 故此,本文通过讲解在本地部署 DeepSeek并配合python代码实现,让你零成本搭建自己的AI…...
【Linux】浅谈冯诺依曼和进程
一、冯诺依曼体系结构 冯诺依曼由 输入设备、输出设备、运算器、控制器、存储器 五部分组成。 冯诺依曼的设计特点 二进制表示 所有数据(包括程序指令)均以二进制形式存储和运算,简化了硬件逻辑设计,提高了可靠性。 存储程序原理…...
基于深度学习的多模态人脸情绪识别研究与实现(视频+图像+语音)
这是一个结合图像和音频的情绪识别系统,从架构、数据准备、模型实现、训练等。包括数据收集、预处理、模型训练、融合方法、部署优化等全流程。确定完整系统的组成部分:数据收集与处理、模型设计与训练、多模态融合、系统集成、部署优化、用户界面等。详…...
【蓝桥杯】第15届c++B组--R格式
问题描述 小蓝最近在研究一种浮点数的表示方法:RR 格式。对于一个大于 0 的浮点数 dd,可以用 RR 格式的整数来表示。给定一个转换参数 nn,将浮点数转换为 RR 格式整数的做法是: 将浮点数乘以 2n2n; 四舍五入到最接近的整数。 …...
【初阶三】认识C语言—下
【初阶三】认识C语言—下 1.函数2.数组3.操作符3.1算数操作符3.2移位操作符和位操作符3.3赋值操作符3.4单目操作符 4.常见关键字4.1关键字typedef4.2 关键字static 5. define定义常宏6.指针6.1内存6.2取地址操作符& 7.结构体 1.函数 函数就像一个工厂,通过输入原…...
【C#】使用DeepSeek帮助评估数据库性能问题,C# 使用定时任务,每隔一分钟移除一次表,再重新创建表,和往新创建的表追加5万多条记录
🌹欢迎来到《小5讲堂》🌹 🌹这是《C#》系列文章,每篇文章将以博主理解的角度展开讲解。🌹 🌹温馨提示:博主能力有限,理解水平有限,若有不对之处望指正!&#…...
前端学习笔记(三)——ant-design vue表单传递数据到父页面
前言 善用AI,快速解决定位 原理 a-form所在的SFC(单文件)vue中需要将表单数据传递给父页面SFC文件中,使用emit方法 代码 子组件(Form.vue) <template><a-form submit"handleSubmit&qu…...
计算机视觉算法实战——驾驶员玩手机检测(主页有源码)
✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连✨ 1. 领域简介:玩手机检测的重要性与技术挑战 驾驶员玩手机检测是智能交通安全领域的核心课题。根据NHTSA数据࿰…...
C语言(23)
字符串函数 11.strstr函数 1.1函数介绍: 头文件:string.h char *strstr ( const char * str1,const char *str2); 作用:在一个字符串(str1)中寻找另外一个字符串(str2)是否出现过 如果找到…...
Python入门教程:从零开始学习Python编程
引言 Python是一种高级编程语言,因其简洁的语法和强大的功能而广受欢迎。无论你是编程新手,还是有经验的开发者,Python都是一个非常好的选择。本文将带你从零开始学习Python编程,涵盖基础语法、常用库以及一些实用的编程技巧。 目…...
SAIL-RK3576核心板应用方案——无人机视觉定位与地面无人设备通信控制方案
本方案以 EFISH-RK3576-SBC工控板 或 SAIL-RK3576核心板 为核心,结合高精度视觉定位、实时通信与智能控制技术,实现无人机与地面无人设备的协同作业。方案适用于物流巡检、农业植保、应急救援等场景,具备高精度定位、低延迟通信与强环境适应性…...
14.C语言const的使用规范,详细说明
目录 修饰变量 修饰指针 指向常量的指针 常量指针 指向常量的常量指针 修饰函数参数 修饰函数返回值 总结 在 C 语言里,const 是一个类型限定符,它的作用是将变量定义为只读,也就是不允许对其值进行修改,用来修饰函数中的…...
安装操作系统ubuntu-20.04.6-live-server-amd64
一、下载虚拟机软件、远程控制软件及操作系统镜像 下载VMware Workstation: 下载 VMware Workstation Pro 个人免费版(可能会访问不了,那就随便找个能下载的版本安装)下载XShell: XShell 家庭/学校免费版下载ubuntu操作系统 ubuntu-20.04.6-…...
使用 PaddleNLP 在 CPU(支持 AVX 指令)下跑通 llama2-7b或DeepSeek-r1:1.5b 模型(完成度80%)
原文:🚣♂️ 使用 PaddleNLP 在 CPU(支持 AVX 指令)下跑通 llama2-7b 模型 🚣 — PaddleNLP 文档 使用 PaddleNLP 在 CPU(支持 AVX 指令)下跑通 llama2-7b 模型 🚣 PaddleNLP 在支持 AVX 指令的 CPU 上对 llama 系列模型进行了…...
【Golang】第五弹----函数
笔上得来终觉浅,绝知此事要躬行 🔥 个人主页:星云爱编程 🔥 所属专栏:Golang 🌷追光的人,终会万丈光芒 🎉欢迎大家点赞👍评论📝收藏⭐文章 目录 一、函数 1.1基本介绍…...
适合二次开发的Web组态软件推荐
在选择适合二次开发的Web组态软件时,需要考虑多个因素,包括开源与否、功能、社区支持、文档完整性等。以下是一些适合二次开发的Web组态软件: 1. Node-RED 简介: Node-RED 是一个基于流的编程工具,最初由IBM开发,现为…...
三、Docker 集群管理与应用
(一)项目案例 1、准备主机 (1)关闭防火墙,或者开放TCP端口2377(用于集群管理通信)、TCP/UPD端口7946(用于节点之间的通信)、UDP端口4789(用于overlay网络流…...
Spring 注解解析
一、Import 1、核心作用 Import 是 Spring 模块化配置的核心注解,用于将外部配置类、组件或动态逻辑导入当前 Spring 上下文。其核心功能包括: 配置类聚合:整合多个分散的 Configuration 类,解决大型项目中配置分散的问题。动态…...
DeepSeek-R1思路训练多模态大模型-Vision-R1开源及实现方法思路
刚开始琢磨使用DeepSeek-R1风格训练多模态R1模型,就看到这个工作,本文一起看看,供参考。 先提出问题,仅靠 RL 是否足以激励 MLLM 的推理能力? 结论:不能,因为如果 RL 能有效激励推理能力&#…...
mysql select distinct 和 group by 哪个效率高
在有索引的情况下,SELECT DISTINCT和GROUP BY的效率相同;在没有索引的情况下,SELECT DISTINCT的效率高于GROUP BY。这是因为SELECT DISTINCT和GROUP BY都会进行分组操作,但GROUP BY可能会进行排序,触发filesort&…...
阿里云操作系统控制台评测:国产AI+运维 一站式运维管理平台
阿里云操作系统控制台评测:国产AI运维 一站式运维管理平台 引言 随着云计算技术的飞速发展,企业在云端的运维管理面临更高的要求。阿里云操作系统控制台作为一款集运维管理、智能助手和系统诊断等多功能于一体的工具,正逐步成为企业高效管理…...
Linux基础开发工具—vim
目录 1、vim的概念 2、vim的常见模式 2.1 演示切换vim模式 3、vim命令模式常用操作 3.1 移动光标 3.2 删除文字 3.3 复制 3.4 替换 4、vim底行模式常用命令 4.1 查找字符 5、vim的配置文件 1、vim的概念 Vim全称是Vi IMproved,即说明它是Vi编辑器的增强…...
11 应用层的域名知识点
一、DNS 1、理解 定义:DNS(Domain Name System,域名系统)是互联网的一项核心服务,它将人类可读的域名(也叫网址,如 www.example.com)转换为机器可读的IP地址(如 192.0.…...
5-24 色彩与风格——T2IA自适应
前言: 上一节我们介绍了ControlNet中的inpaint局部重绘 主要介绍ControlNet中的T2IA自适应。 色彩风格的参考和借鉴能力,有点类似于5-17 reference参考图 或者 5-16 画面风格迁移-shuffle洗牌 。当然在硬件的要求,软件的算法实现和使用方式…...
JAVA-Thread类实现多线程
引言: 本章博客涉及进程线程内容,如果不了解的可以看:什么是进程线程-CSDN博客 线程是操作系统的概念,操作系统提供的API供程序员使用操作。但是不同的操作系统(Winodws、Linux、Unix……差别很大),但是做为JAVA程序员就不需要担心…...
顺序表,单链表,双链表,循环链表(01星球)
文章目录 数据结构前导------C语言复习程序为什么要被编译器编译之后才能运行编译器把C语言程序转换成可以执行的机器码的过程做了什么宏定义typedef 关键字全局变量和局部变量常量字符的输入输出运算符冯诺依曼架构存储器容量数据类型指针指针本质为什么需要指针 数组数组指针…...
代码社区开源协议
开源协议是一种法律文件,用于规定开源软件的使用、修改和分发条件。它平衡了开发者和使用者的权益,同时推动开放协作与技术创新。以下是常见的开源协议及其特点和适用场景: 常见开源协议列表及介绍 1. MIT License 特点:非常宽…...
[免费]微信小程序(图书馆)自习室座位预约管理系统(SpringBoot后端+Vue管理端)(高级版)【论文+源码+SQL脚本】
大家好,我是java1234_小锋老师,看到一个不错的微信小程序(图书馆)自习室座位预约管理系统(SpringBoot后端Vue管理端)(高级版),分享下哈。 项目视频演示 【免费】微信小程序(图书馆)自习室座位预约管理系统(SpringBoot后端Vue管理端)(高级版…...
树莓派:更新源
发行版本 Debian 一直维护着至少三个发行版本:“稳定版(stable)”,“测试版(testing)”和“不稳定版(unstable)”。 发行版目录 下一代 Debian 正式发行版的代号为 bullseye — 发布…...
树与二叉树的遍历
我们平时用的树都是二叉树 一、一些基础概念 1. 树就是一种:一对多的数据结构。树离不开递归,因为“树”就是“树”中有“树”。 二叉树就是 :空树 或者 每个结点的子结点个数小于等于2。 满二叉树: 除叶子结点外所有结点的…...
Web基础:HTML快速入门
HTML基础语法 HTML(超文本标记语言) 是用于创建网页内容的 标记语言,通过定义页面的 结构和内容 来告诉浏览器如何呈现网页。 超文本(Hypertext) 是一种通过 链接(Hyperlinks) 将不同文本、图像…...
异常(8)
今天补充一些异常的细节,帮助大家更好的理解异常. 注:关于异常的处理方式 异常的种类有很多,我们要根据不同的业务场景来决定. 对于比较严重的问题(例如和算钱相关的场景),应该让程序直接崩溃,防止造成更严重的结果 对于不太严重的问题(大多数场景),可以记录错误日志,并通过…...
平时作业
java作业 package zuoye; public class zuoye02 {public static int Random(int n) {return (int)(n * Math.random());}public static void main(String[] args) {int n 100;//System.out.println(Random(n));int[]random new int[50];for(int i 0; i <50; i) {rand…...
宇树人形机器人开源模型
1. 下载源码 https://github.com/unitreerobotics/unitree_ros.git2. 启动Gazebo roslaunch h1_description gazebo.launch3. 仿真效果 H1 GO2 B2 Laikago Z1 4. VMware: vmw_ioctl_command error Invalid argument 这个错误通常出现在虚拟机环境中运行需要OpenGL支持的应用…...
**ResNet-SE + MFCC** 训练框架,包括 **数据加载、训练流程**,以及 **混淆矩阵** 可视化示例
1. 依赖库安装 如果你还没安装相关库,请先执行: pip install torch torchaudio torchvision scikit-learn matplotlib tqdm2. 数据加载 这里假设你有一个 音频分类数据集,其文件结构如下: dataset/ │── train/ │ ├──…...
Golang | 每日一练 (5)
💢欢迎来到张胤尘的技术站 💥技术如江河,汇聚众志成。代码似星辰,照亮行征程。开源精神长,传承永不忘。携手共前行,未来更辉煌💥 文章目录 Golang | 每日一练 (5)题目参考答案线程与协程线程切换…...