You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 22:02:18