使用 SseEmitter 實現 Spring Boot 后端的流式傳輸和前端的數據接收

1.普通文本消息的發送和接收

@GetMapping("/stream")public SseEmitter streamResponse() {SseEmitter emitter = new SseEmitter(0L); // 0L 表示永不超時Executors.newSingleThreadExecutor().execute(() -> {try {for (int i = 1; i <= 5; i++) {emitter.send("消息 " + i);Thread.sleep(1000); // 模擬延遲}emitter.complete();} catch (Exception e) {emitter.completeWithError(e);}});return emitter;}
async function fetchStreamData() {const response = await fetch("/api/chat/stream");// 確保服務器支持流式數據if (!response.ok) {throw new Error(`HTTP 錯誤!狀態碼: ${response.status}`);}const reader = response.body.getReader();const decoder = new TextDecoder("utf-8");// 讀取流式數據while (true) {const { done, value } = await reader.read();if (done) break;// 解碼并輸出數據const text = decoder.decode(value, { stream: true });console.log("收到數據:", text);}console.log("流式傳輸完成");
}
// 調用流式請求
fetchStreamData().catch(console.error);

2.使用流式消息發送多個文件流,實現多個文件的傳輸

//這里相當于每個drawCatalogue對象會創建一個文件流,然后發送過去,list中有幾個對象就會發送幾個文件
//之所以要每個屬性都手動write一下,是因為我的每個ajaxResult數據量都特別大,容易內存溢出。如果沒有我這種特殊情況的話,直接使用JSONObject.toJSONString(drawCatalogue)就可以,不需要去手動寫入每個屬性。
public SseEmitter getAllDrawDataThree(String cadCode) {SseEmitter sseEmitter = new SseEmitter(Long.MAX_VALUE); // 設置超時時間為最大值,防止自動結束try {Long code = Long.parseLong(cadCode);DrawExcelList drawExcelList = new DrawExcelList();drawExcelList.setCadCode(code);List<DrawCatalogue> drawCatalogueList = drawExcelListService.treeTableCatalogue(drawExcelList);int splitSize = 20;List<DrawCatalogue> newDrawCatalogueList = splitDrawCatalogueList(drawCatalogueList, splitSize);for (int i = 0; i < newDrawCatalogueList.size(); i++) {String filePath = "drawCatalogue" + i + ".json"; // 文件路徑DrawCatalogue drawCatalogue = newDrawCatalogueList.get(i);try (BufferedWriter writer = new BufferedWriter(new FileWriter(filePath))) {writer.write("["); // 開始寫入最外層JSON數組writer.write("{");writer.write("\"id\": \"" + drawCatalogue.getId() + "\",");writer.write("\"drawName\": \"" + drawCatalogue.getDrawName() + "\",");writer.write("\"drawType\": \"" + drawCatalogue.getDrawType() + "\",");writer.write("\"combineOutType\": \"" + drawCatalogue.getCombineOutType() + "\",");writer.write("\"num\": \"" + drawCatalogue.getNum() + "\",");writer.write("\"children\": ");writer.write("["); // 開始寫入childrenJSON數組boolean first = true; // 用于判斷是否是第一個元素List<DrawCatalogue> children = drawCatalogue.getChildren();for (DrawCatalogue child : children) {DrawingMain drawingMain = new DrawingMain();drawingMain.setCadCode(code);drawingMain.setDrawName(child.getCombineOutType());drawingMain.setDrawType(child.getDrawType());AjaxResult ajaxResult = drawingMainService.imgListShow(drawingMain);if (!first) {writer.write(","); // 如果不是第一個元素,寫入逗號分隔}String tabletJson = JSONObject.toJSONString(ajaxResult);// 逐個屬性寫入文件流writer.write("{");writer.write("\"id\": \"" + child.getId() + "\",");writer.write("\"drawName\": \"" + child.getDrawName() + "\",");writer.write("\"combineOutType\": \"" + child.getCombineOutType() + "\",");writer.write("\"drawType\": \"" + child.getDrawType() + "\",");writer.write("\"tabletJson\": " + tabletJson);writer.write("}");first = false; // 標記已經寫入了一個元素}writer.write("]"); // 結束children數組writer.write("}");writer.write("]"); // 結束最外層JSON數組} catch (IOException e) {sseEmitter.completeWithError(e);}// 讀取并發送文件流//byte[] fileData = Files.readAllBytes(Paths.get(filePath));// 分塊讀取文件并發送(防止一次性讀取的文件過大導致內存溢出)Path path = Paths.get(filePath);ByteArrayOutputStream outputStream = new ByteArrayOutputStream();byte[] buffer = new byte[8192]; // 8KB buffertry (InputStream in = Files.newInputStream(path)) {int bytesRead;while ((bytesRead = in.read(buffer)) != -1) {outputStream.write(buffer, 0, bytesRead);}}byte[] fileData = outputStream.toByteArray();sseEmitter.send(fileData, MediaType.APPLICATION_OCTET_STREAM);}sseEmitter.complete();} catch (Exception e) {sseEmitter.completeWithError(e);} finally {sseEmitter.complete();}return sseEmitter;}

前端代碼,在方法中調用,后端返回幾個文件就會彈出幾個下載窗口

				const eventSource = new EventSource('http://127.0.0.1:1801/tablet/getAllDrawDataThree');eventSource.onmessage = function(event) {try {const fileData = event.data;const blob = new Blob([fileData], { type: 'application/octet-stream' });const url = window.URL.createObjectURL(blob);const a = document.createElement('a');a.style.display = 'none';a.href = url;a.download = 'file.json'; // 設置下載文件名document.body.appendChild(a);a.click();window.URL.revokeObjectURL(url);document.body.removeChild(a);} catch (error) {console.error('Error processing event data:', error);}};eventSource.onerror = function(event) {console.error('SSE error:', event);};

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/908133.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/908133.shtml
英文地址,請注明出處:http://en.pswp.cn/news/908133.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

nssm配置springboot項目環境,注冊為windows服務

NSSM 的官方下載地址是&#xff1a;NSSM - the Non-Sucking Service Manager1 使用powershell輸入命令,java項目需要手動配置和依賴nacos .\nssm.exe install cyMinio "D:\minio\啟動命令.bat" .\nssm.exe install cyNacos "D:\IdeaProject\capacity\nacos-s…

WinCC學習系列-基礎概念

從本節起&#xff0c;學習和了解西門子最新SCADA軟件WinCC 8.0&#xff0c;將從基礎概念開始&#xff0c;到入門操作&#xff08;創建項目、組態通信、組態過程畫面、組態面板類型和變量結構、歸檔和顯示值、組態消息&#xff09;&#xff0c;到高級應用&#xff08;WinCC選件、…

數據分析圖表類型及其應用場景

說明&#xff1a;頂部HTML文件下載后可以直接查看&#xff0c;帶有示圖。 摘要 數據可視化作為現代數據分析的核心環節&#xff0c;旨在將復雜、抽象的數據轉化為直觀、易懂的圖形形式。這種轉化顯著提升了業務決策能力&#xff0c;優化了銷售與營銷活動&#xff0c;開辟了新…

《江西棒壘球》敗方mvp叫什么·棒球1號位

敗方mvp也是MVP&#xff0c;以棒球運動為例&#xff0c;MLB&#xff08;美國職棒大聯盟&#xff09;的個人獎項旨在表彰球員在不同領域的卓越表現&#xff0c;涵蓋常規賽和季后賽的杰出成就。 常規賽核心獎項 最有價值球員獎&#xff08;MVP&#xff09; 定義&#xff1a;表彰…

CD43.vector模擬實現(2)

目錄 1.拷貝構造函數 寫法1 寫法2 測試代碼 調試找bug 解決方法:修改拷貝構造函數 測試代碼 2.operator[ ] 測試代碼 1.沒有const修飾 2.有const修飾 3.insert 迭代器失效問題 承接CD42.vector模擬實現(1)文章 1.拷貝構造函數 設置start、finish和end_of_storag…

【C/C++】入門grpc的idl

文章目錄 grpc idl 簡單介紹1. 文件結構組織規范文件命名包結構&#xff1a;推薦&#xff1a;一個文件只定義一個 service&#xff0c;如果 service 很復雜&#xff0c;可拆分多個 proto 文件。 2. 消息定義規范命名風格字段編號&#xff1a;示例&#xff1a; 3. 服務與 RPC 設…

安全-JAVA開發-第二天

Web資源訪問的流程 由此可見 客戶訪問JAVA開發的應用時 會先通過 監聽器&#xff08;Listener&#xff09;和 過濾器&#xff08;Filter&#xff09; 今天簡單的了解下這兩個模塊的開發過程 監聽器&#xff08;Listener&#xff09; 主要是監聽 我們觸發了什么行為 并進行反應…

使用 Ansys Q3D 進行電容提取

精確的電容提取在高速和 RF 設計中至關重要。雖然簡單的公式可以提供一個很好的起點&#xff0c;但它們往往無法捕捉 fringing fields 和 layout-dependent parasitics 的影響。在本博客中&#xff0c;我們演示了如何使用Ansys Q3D Extractor來計算電容值&#xff0c;從基本的平…

卡西歐模擬器:Windows端功能強大的計算器

引言 大家還記得初中高中時期用的計算器嗎&#xff1f;今天給大家分享的就是一款windows端的卡西歐計算器。 軟件介紹 大家好&#xff0c;我是逍遙小歡。 CASIO fx-9860G是一款功能強大的圖形計算器&#xff0c;適用于數學、科學和工程計算。以下是其主要功能和特點的詳細介…

【Bluedroid】藍牙啟動之gatt_init 流程源碼解析

本文圍繞Android藍牙協議棧中 GATT(通用屬性配置文件)模塊的初始化函數gatt_init展開,深入解析其核心實現邏輯與關鍵步驟。通過分析gatt_init及其關聯子函數(如L2CA_RegisterFixedChannel、gatt_profile_db_init、EattExtension::Start等),以及相關數據結構(如tGATT_CB控…

Vue 3 中ref 結合ts 獲取 DOM 元素的實踐指南。

文章目錄 前言一、為什么需要為 ref 添加類型&#xff1f;二、基本用法&#xff1a;引用 DOM 元素1. 引用通用 DOM 元素&#xff08;HTMLElement&#xff09;2. 引用特定類型的 DOM 元素&#xff08;如 HTMLDivElement&#xff09; 三、<script setup> 語法中的類型定義四…

Axure形狀類組件圖標庫(共8套)

點擊下載《月下倚樓圖標庫(形狀組件)》 原型效果&#xff1a;https://axhub.im/ax9/02043f78e1b4386f/#g1 摘要 本圖標庫集錦精心匯集了8套專為Axure設計的形狀類圖標資源&#xff0c;旨在為產品經理、UI/UX設計師以及開發人員提供豐富多樣的設計素材&#xff0c;提升原型設計…

01串(二進制串)與集合之間存在天然的對應關系 ← bitset

【集合的二進制表示?】 ● 01 串&#xff08;二進制串&#xff09;與集合之間存在天然的對應關系。對應機理為每個二進制位可以表示集合中一個元素的存在&#xff08;1&#xff09;或不存在&#xff08;0&#xff09;。例如&#xff0c;集合 {a, b, c} 的子集 {a, c} 可以表示…

vba學習系列(10)--外觀報表

系列文章目錄 文章目錄 系列文章目錄前言一、外觀報表1.產能統計2.單板數3.固定傷排查4.件號良率5.鏡片批退率6.鏡筒批退率 總結 前言 一、外觀報表 1.產能統計 Sub ProcessInspectionData()Dim ws1 As Worksheet, ws2 As Worksheet, ws3 As WorksheetDim lastRow1 As Long, …

machine_env_loader must have been assigned before creating ssh child instance

在主機上執行roslaunch命令時&#xff0c;報錯&#xff1a;machine_env_loader must have been assigned before creating ssh child instance。 解決辦法&#xff1a; 打開hostos文件&#xff0c;檢查local host 前的內部ip是否正常。操作示例&#xff1a; 先輸入下方指令打…

CSS radial-gradient函數詳解

目錄 基本語法 關鍵參數詳解 1. 漸變形狀&#xff08;Shape&#xff09; 2. 漸變大小&#xff08;Size&#xff09; 3. 中心點位置&#xff08;Position&#xff09; 4. 顏色斷點&#xff08;Color Stops&#xff09; 常見應用場景 1. 基本圓形漸變 2. 橢圓漸變 3. 模…

分析Web3下數據保護的創新模式

在這個信息爆炸的時代&#xff0c;我們正站在 Web3 的門檻上&#xff0c;迎接一個以去中心化、用戶主權和數據隱私為核心的新時代。Web3 不僅僅是技術的迭代&#xff0c;它更是一場關于數據權利和責任的結構性變革。本文將探討 Web3 下數據保護的創新模式&#xff0c;以期為用戶…

RabbitMQ-Go 性能分析

更多個人筆記見&#xff1a; &#xff08;注意點擊“繼續”&#xff0c;而不是“發現新項目”&#xff09; github個人筆記倉庫 https://github.com/ZHLOVEYY/IT_note gitee 個人筆記倉庫 https://gitee.com/harryhack/it_note 個人學習&#xff0c;學習過程中還會不斷補充&…

AI助力Java開發:減少70%重復編碼,實戰效能提升解析

工具再先進&#xff0c;也替代不了編程思維的深度錘煉 在Java開發領域&#xff0c;重復編碼如同無形的生產力黑洞——以商品管理模塊開發為例&#xff0c;開發者耗費大量時間編寫SQL查詢、處理結果集轉換&#xff1b;用戶系統里&#xff0c;密碼加密和狀態管理的代碼在不同項目…

JS語法筆記

目錄 JS數組Array新建數組一維數組二維數組 reverse()在數組末尾插入&#xff1a;push()在數組末尾刪除&#xff1a;pop()在數組開頭插入&#xff1a;unshift()從數組開頭刪除一個元素shift()splice() MapSet JS數組Array 判斷數組相等不能用&#xff0c;要循環判斷 新建數組…