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

如何在Django中使用StreamingHttpResponse流式传输数据并通过Axios在前端分块接收(解决数据缓冲问题)

如何在Django中使用StreamingHttpResponse流式传输数据并通过Axios在前端分块接收(解决数据缓冲问题)

看起来你遇到的核心问题是流式响应被中间件或服务器端缓冲,导致前端无法实时接收分块数据。结合你的代码和常见的坑,我来帮你一步步解决:

1. 处理中间件的缓冲干扰

你的中间件里用到了WhiteNoiseMiddleware,它默认会缓冲响应以优化静态文件传输,但这会破坏流式响应的实时性。解决方法很简单,在你的视图响应中添加一个专属头,告诉WhiteNoise不要缓冲这个请求:

response['WhiteNoise-No-Buffering'] = 'true'

另外,建议补充更严格的缓存禁用头,避免其他层级(比如浏览器、代理)的缓冲:

response['Cache-Control'] = 'no-cache, no-store, must-revalidate'
response['Pragma'] = 'no-cache'
response['Expires'] = '0'

2. 确保流式输出的分隔符正确

Django的StreamingHttpResponse依赖yield的内容来分割块,但如果输出内容没有明确的分隔标记,服务器或浏览器可能会合并多个小块。建议在每个yield的内容末尾添加换行符,确保每个块能被正确识别:

def iterator():
    for i in range(1000):
        # 添加换行符作为块分隔
        yield f'chunk: {i}\n'
        time.sleep(0.2)

3. 前端Axios的配置调整

你的前端代码里有两个关键问题:

  • 默认的responseType是json,Axios会等待全部数据接收完成后才解析,这直接导致无法实时获取分块
  • onDownloadProgress里直接取response会拿到累积的所有数据,而不是当前新收到的块

修改后的前端代码如下,添加responseType: 'text'并跟踪已接收的位置:

// 全局变量跟踪已接收的字节长度,避免重复处理
let lastReceivedLength = 0;

axios({
    url: '/api/gpt3/generate-post-text',
    method: 'GET',
    responseType: 'text', // 必须设置为text,禁止自动等待完整数据解析
    onDownloadProgress: progressEvent => {
        const fullResponse = progressEvent.currentTarget.response;
        // 提取本次新收到的块内容
        const newChunk = fullResponse.slice(lastReceivedLength);
        
        if (newChunk.trim()) { // 过滤空内容
            console.log('实时接收的块:', newChunk.trim());
            lastReceivedLength = fullResponse.length;
        }
    },
}).then(({data}) => {
    console.log('全部数据接收完成:', data);
}).catch(err => {
    console.error('请求出错:', err);
});

完整的后端修改代码

把上面的优化点整合后,你的后端视图应该是这样的:

import time
from django.http import StreamingHttpResponse

def iterator():
    for i in range(1000):
        yield f'chunk: {i}\n'
        time.sleep(0.2)

def generate_post_text(request):
    stream = iterator()
    response = StreamingHttpResponse(
        stream, 
        status=200,
        content_type='text/event-stream'
    )
    # 禁用所有层级的缓冲
    response['Cache-Control'] = 'no-cache, no-store, must-revalidate'
    response['Pragma'] = 'no-cache'
    response['Expires'] = '0'
    response['X-Accel-Buffering'] = 'no'
    # 让WhiteNoise跳过缓冲处理
    response['WhiteNoise-No-Buffering'] = 'true'
    # 明确指定分块传输
    response['Transfer-Encoding'] = 'chunked'
    return response

额外注意事项

  • 如果你用的是生产环境的WSGI服务器(比如Gunicorn),需要确保它启用了流式支持,Gunicorn默认是支持的,但不要设置--worker-class=gthread以外的其他worker类型(比如gevent可能需要额外配置)
  • 本地开发的runserver本身是支持流式响应的,所以修改后应该能直接看到效果

备注:内容来源于stack exchange,提问作者Pourya Delnavaz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.23 15:22:42