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.pswp.cn/news/897603.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/897603.shtml
英文地址,請注明出處:http://en.pswp.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, …