Flask中SSE使用问题:如何将流式内容展示在index.html页面
解决方案
要实现从stream_page.html发起POST请求触发/stream路由,并将流式内容展示在index.html中,需要调整前端请求方式和页面间通信逻辑,具体步骤如下:
1. 调整Flask后端路由
保留流式生成逻辑,确保路由仅接收POST请求:
from flask import Flask, request, Response import time app = Flask(__name__) @app.route('/stream', methods=['POST']) def stream(): data = request.form['data'] def gen(input_data): # 这里替换为你的实际业务流式生成逻辑 for i in range(5): yield f"data: 第{i+1}段输出,输入内容:{input_data}\n\n" time.sleep(1) # 发送流式结束标识 yield "event: close\ndata: 流式输出已结束\n\n" return Response(gen(data), content_type='text/event_stream') if __name__ == '__main__': app.run(debug=True)
2. 修改stream_page.html:拦截表单提交,处理流式响应
阻止表单默认跳转,用AJAX发起POST请求获取流式数据,并通过Broadcast Channel将内容传递给index.html:
<form id="streamForm"> <input type="text" name="data" placeholder="输入触发数据" required> <button type="submit">启动流式输出</button> </form> <script> // 创建跨页面通信的广播频道 const streamChannel = new BroadcastChannel('stream_content_channel'); document.getElementById('streamForm').addEventListener('submit', async (e) => { e.preventDefault(); // 阻止表单默认跳转行为 const formData = new FormData(e.target); const response = await fetch('/stream', { method: 'POST', body: formData }); if (!response.ok) { console.error('请求失败:', response.statusText); return; } // 读取流式响应内容 const reader = response.body.getReader(); const decoder = new TextDecoder(); while (true) { const { done, value } = await reader.read(); if (done) break; // 解析SSE格式的响应文本 const rawText = decoder.decode(value, { stream: true }); const messages = rawText.split('\n\n').filter(item => item.trim()); messages.forEach(msg => { const lines = msg.split('\n'); let content = ''; let eventType = ''; lines.forEach(line => { if (line.startsWith('data:')) { content = line.slice(5).trim(); } else if (line.startsWith('event:')) { eventType = line.slice(6).trim(); } }); if (content) { // 向广播频道发送流式内容 streamChannel.postMessage({ type: eventType || 'message', content: content }); } }); } }); </script>
3. 修改index.html:监听广播频道,渲染流式内容
连接同一广播频道,接收stream_page.html传来的内容并展示在页面上:
<div id="events_container" style="margin: 20px; padding: 10px; border: 1px solid #eee;"></div> <script> // 连接广播频道 const streamChannel = new BroadcastChannel('stream_content_channel'); streamChannel.onmessage = (msg) => { const container = document.getElementById('events_container'); if (msg.data.type === 'close') { const endElement = document.createElement('p'); endElement.style.color = '#666'; endElement.textContent = msg.data.content; container.appendChild(endElement); return; } // 创建元素展示流式内容 const contentElement = document.createElement('div'); contentElement.style.margin = '8px 0'; contentElement.textContent = msg.data.content; container.appendChild(contentElement); }; // 页面关闭时关闭频道 window.addEventListener('beforeunload', () => { streamChannel.close(); }); </script>
核心逻辑说明
- 避免页面跳转:通过
e.preventDefault()拦截表单默认提交行为,改用AJAX发起请求,不会打开新空白页。 - 跨页面通信:利用Broadcast Channel API实现同域下两个页面的实时消息传递,确保流式内容直接发送到
index.html。 - 流式数据处理:通过
ReadableStream读取后端返回的SSE格式数据,解析后传递给目标页面展示。
内容的提问来源于stack exchange,提问作者miara
相关产品推荐
相关产品推荐

