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>

上传测试结果:
 

下载测试:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/897603.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

手把手教你用Docker搭建gitlab

文章目录 前言一、安装Docker二、安装GItlab三、配置Gitlab四、备份五、Docker数据持久化总结 前言 如题所述&#xff0c;手把手带你搭建gitlab&#xff0c;目标是实现ssh链接clone项目&#xff0c;不会我随你怎么说。 说正题&#xff0c;GitLab 是一个基于 Git 的全面 DevOps…

基于springboot住院管理系统(源码+lw+部署文档+讲解),源码可白嫖!

摘要 随着世界经济信息化、全球化的到来和电子商务的飞速发展&#xff0c;推动了很多行业的改革。若想达到安全&#xff0c;快捷的目的&#xff0c;就需要拥有信息化的组织和管理模式&#xff0c;建立一套合理、畅通、高效的线上管理系统。当前的住院管理存在管理效率低下&…

JVM常用概念之常量

问题 final修饰的字段就一定是不能重新赋值吗? 基础知识 常量变量是使用常量表达式初始化的原始类型或 String 类型的最终变量。变量是否为常量变量可能对类初始化、二进制兼容性和明确赋值有影响。 —Java 语言规范 实验 用例源码-重新赋值 import java.lang.reflect.Fie…

数据采集技术之python网络爬虫(中国天气网的爬取)

一、爬取中国天气网所有地区当天的天气数据&#xff08;PyCharm&#xff09;&#xff1a; 网址&#xff1a;https://www.weather.com.cn/ 下面爬取数据&#xff1a; 因为现在已经到了夜间&#xff0c;所以白天的数据已经不见了&#xff0c;但原理是一样的。 二、代码以及详情…

树莓集团落子海南,如何重构数字产业生态体系​

树莓集团在海南的布局&#xff0c;是其整体商业战略中的关键一环。这背后&#xff0c;是对政策机遇、产业协同、以及区域优势的深度考量。 政策机遇 海南自贸港建设带来前所未有的政策红利&#xff0c;包括贸易、投资、资金等方面的自由便利。树莓集团紧抓这一机遇&#xff0…

Ollama本地部署deepseek-r1蒸馏版

Docker安装Ollama 拉取镜像 docker pull ollama/ollama​ 启动-使用GPU docker run -d --gpusall -p 11434:11434 --name ollama ollama/ollamadocker run : Docker 的核心命令&#xff0c;用于创建并启动一个新的容器。 -d : 后台模式&#xff08;detached mode&#xff09…

41.HarmonyOS NEXT Layout布局组件系统详解(八):自定义样式与类

温馨提示&#xff1a;本篇博客的详细代码已发布到 git : https://gitcode.com/nutpi/HarmonyosNext 可以下载运行哦&#xff01; HarmonyOS NEXT Layout 布局组件系统详解&#xff08;八&#xff09;&#xff1a;自定义样式与类 文章目录 HarmonyOS NEXT Layout 布局组件系统详…

【Go | 从0实现简单分布式缓存】-7:增加etcd和gRPC功能

本文目录 1.序2.引入etcd缓存流程项目结构 3.gocachepb.proto4.服务注册register.go5.服务发现discover.go6.gRPC客户端client.gopeers.goclient.go 7.gRPC服务端实现server.go一些问题缓存获取流程缓存设置流程为什么要带超时的上下文&#xff1f; 1.序 GeeCache项目并没有引…

Pytorch系列教程:可视化Pytorch模型训练过程

深度学习和理解训练过程中的学习和进步机制对于优化性能、诊断欠拟合或过拟合等问题至关重要。将训练过程可视化的过程为学习的动态提供了有价值的见解&#xff0c;使我们能够做出合理的决策。训练进度必须可视化的两种方法是&#xff1a;使用Matplotlib和Tensor Board。在本文…

18 | 实现简洁架构的 Handler 层

提示&#xff1a; 所有体系课见专栏&#xff1a;Go 项目开发极速入门实战课&#xff1b;欢迎加入我的训练营&#xff1a;云原生AI实战营&#xff0c;一个助力 Go 开发者在 AI 时代建立技术竞争力的实战营&#xff1b;本节课最终源码位于 fastgo 项目的 feature/s14 分支&#x…

蓝队第三次

1.了解什么是盲注 盲注&#xff08;Blind SQL Injection&#xff09;是SQL注入的一种形式&#xff0c;攻击者无法直接通过页面回显或错误信息获取数据&#xff0c;而是通过观察页面的布尔状态&#xff08;真/假&#xff09;或时间延迟来间接推断数据库信息。例如&#xff0c;通…

sql server 2016 版本补丁说明

包信息和发布类型 Microsoft为创建和分发的 SQL Server 的所有软件更新包采用了标准化命名架构。 软件更新包是一个可执行文件&#xff08;.exe 或 .msi&#xff09;文件&#xff0c;其中包含一个或多个文件&#xff0c;这些文件可能应用于 SQL Server 安装以更正特定问题。 …

STM32之I2C硬件外设

注意&#xff1a;硬件I2C的引脚是固定的 SDA和SCL都是复用到外部引脚。 SDA发送时数据寄存器的数据在数据移位寄存器空闲的状态下进入数据移位寄存器&#xff0c;此时会置状态寄存器的TXE为1&#xff0c;表示发送寄存器为空&#xff0c;然后往数据控制寄存器中一位一位的移送数…

从青铜到王者:六大排序算法实战解析

前言 在编程的世界里,排序算法如同一颗璀璨的明珠,闪耀着智慧的光芒。它不仅是计算机科学的基础知识点,更是每一位程序员必备的技能。今天,就让我们一同走进排序算法的世界,深入探究冒泡排序、选择排序、插入排序、快速排序、归并排序、堆排序这六大经典算法的精髓所在,…

小程序配置webview

1.在微信公众平台配置业务域名 1&#xff09;包括把校验文件放在服务器根目录 2&#xff09;配置域名 2.在小程序中 新建文件 小程序新建页面&#xff1a;web-view json配置&#xff1a;{ "pageOrientation": "landscape", "renderer":&qu…

不用 Tomcat?SpringBoot 项目用啥代替?

在SpringBoot框架中&#xff0c;我们使用最多的是Tomcat&#xff0c;这是SpringBoot默认的容器技术&#xff0c;而且是内嵌式的Tomcat。 同时&#xff0c;SpringBoot也支持Undertow容器&#xff0c;我们可以很方便的用Undertow替换Tomcat&#xff0c;而Undertow的性能和内存使…

线索二叉树构造及遍历算法

线索二叉树构造以及遍历算法 线索二叉树&#xff08;中序遍历版&#xff09;构造线索二叉树构造双向线索链表遍历中序线索二叉树 线索二叉树&#xff08;中序遍历版&#xff09; 中序遍历找到对应结点的前驱&#xff08;土方法&#xff09; #mermaid-svg-eunGO5d2GhjLxCn5 {fo…

基于SpringBoot的“体育购物商城”的设计与实现(源码+数据库+文档+PPT)

基于SpringBoot的“体育购物商城”的设计与实现&#xff08;源码数据库文档PPT) 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBoot 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 系统总体模块设计 前台用户登录界面 系统首页界面…

数据篇| App爬虫入门(一)

App 的爬取相比 Web 端爬取更加容易,反爬虫能力没有那么强,而且数据大多是以 JSON 形式传输的,解析更加简单。在 Web 端,我们可以通过浏览器的开发者工具监听到各个网络请求和响应过程,在 App 端如果想要查看这些内容就需要借助抓包软件。常见抓包软件有: ‌工具名称‌‌…

go context学习

1.Context接口2.emptyCtx3.Deadline()方法4.Done()方法5.Err方法6.Value方法&#xff08;&#xff09;7.contex应用场景8.其他context方法 1.Context接口 Context接口只有四个方法&#xff0c;以下是context源码。 type Context interface {Deadline() (deadline time.Time, …