Django使用StreamingHttpResponse實(shí)現(xiàn)流式響應(yīng)的實(shí)現(xiàn)示例
使用 StreamingHttpResponse 來(lái)實(shí)現(xiàn)流式響應(yīng),也就是將數(shù)據(jù)分塊返回給客戶端,而不是一次性返回全部?jī)?nèi)容。這在處理大文件下載、實(shí)時(shí)數(shù)據(jù)推送等場(chǎng)景中非常實(shí)用。
一、基本原理與使用場(chǎng)景
StreamingHttpResponse 是 Django 提供的用于流式傳輸響應(yīng)的類,它不會(huì)一次性將所有響應(yīng)數(shù)據(jù)加載到內(nèi)存中,而是通過(guò)迭代器逐塊發(fā)送數(shù)據(jù),適合:
- 大文件下載(避免內(nèi)存溢出)
- 實(shí)時(shí)生成并返回?cái)?shù)據(jù)(如實(shí)時(shí)日志、進(jìn)度條更新)
- 服務(wù)器推送事件(SSE)等實(shí)時(shí)通信場(chǎng)景
二、基礎(chǔ)使用示例
1. 最簡(jiǎn)單的流式響應(yīng)
先寫一個(gè)基礎(chǔ)示例,逐行返回文本數(shù)據(jù):
from django.http import StreamingHttpResponse
from django.views import View
import time
# 定義生成器函數(shù),用于逐塊生成數(shù)據(jù)
def stream_generator():
"""生成器函數(shù),逐行返回?cái)?shù)據(jù)(模擬實(shí)時(shí)生成內(nèi)容)"""
for i in range(5):
# 模擬耗時(shí)操作(如讀取大文件、實(shí)時(shí)計(jì)算)
time.sleep(1)
# 每塊數(shù)據(jù)末尾加換行符,讓客戶端能實(shí)時(shí)看到
yield f"這是第 {i+1} 塊數(shù)據(jù)\n"
class StreamView(View):
def get(self, request):
# 創(chuàng)建 StreamingHttpResponse,傳入生成器
response = StreamingHttpResponse(stream_generator())
# 設(shè)置響應(yīng)頭,確??蛻舳税戳魈幚恚蛇x但推薦)
response['Content-Type'] = 'text/plain; charset=utf-8'
# 禁用緩存,確保數(shù)據(jù)實(shí)時(shí)推送
response['Cache-Control'] = 'no-cache'
# 添加流式傳輸 headers,禁用緩沖
# 注意:Transfer-Encoding 和 Connection 是 hop-by-hop headers,由 WSGI 服務(wù)器自動(dòng)處理,不能在應(yīng)用層設(shè)置
# response['Cache-Control'] = 'no-cache, no-store, must-revalidate'
# response['Pragma'] = 'no-cache'
# response['Expires'] = '0'
# response['X-Accel-Buffering'] = 'no' # 禁用 Nginx 緩沖
# logger.info(f"[StreamingView] StreamingHttpResponse 已創(chuàng)建,headers 已配置用于流式傳輸")
return response
2. 大文件流式下載
這是更實(shí)用的場(chǎng)景,避免一次性讀取大文件到內(nèi)存:
from django.http import StreamingHttpResponse
from django.views import View
import os
def file_stream_generator(file_path, chunk_size=8192):
"""讀取文件并逐塊生成數(shù)據(jù)"""
with open(file_path, 'rb') as f:
while chunk := f.read(chunk_size):
yield chunk
class LargeFileDownloadView(View):
def get(self, request):
# 替換為你的大文件路徑
file_path = "/path/to/your/large_file.zip"
if not os.path.exists(file_path):
return HttpResponse("文件不存在", status=404)
# 獲取文件名
file_name = os.path.basename(file_path)
# 創(chuàng)建流式響應(yīng)
response = StreamingHttpResponse(
file_stream_generator(file_path),
content_type='application/octet-stream' # 二進(jìn)制文件類型
)
# 設(shè)置下載頭,指定文件名
response['Content-Disposition'] = f'attachment; filename="{file_name}"'
# 設(shè)置分塊傳輸編碼
response['Transfer-Encoding'] = 'chunked'
return response
3. 實(shí)時(shí) SSE(服務(wù)器推送事件)
適用于實(shí)時(shí)通知、進(jìn)度展示等場(chǎng)景:
from django.http import StreamingHttpResponse
from django.views import View
import time
import json
def sse_generator():
"""生成 SSE 格式的實(shí)時(shí)數(shù)據(jù)"""
for i in range(10):
time.sleep(1)
# SSE 格式要求:data: 內(nèi)容\n\n
data = json.dumps({"progress": i * 10, "message": f"處理中 {i*10}%"})
yield f"data: {data}\n\n"
class SSEView(View):
def get(self, request):
response = StreamingHttpResponse(sse_generator())
# SSE 專用 Content-Type
response['Content-Type'] = 'text/event-stream'
# 禁用緩存和超時(shí)
response['Cache-Control'] = 'no-cache'
response['X-Accel-Buffering'] = 'no' # 禁用 nginx 緩沖(關(guān)鍵)
return response
三、關(guān)鍵注意事項(xiàng)
- 生成器必須是迭代器:
StreamingHttpResponse的參數(shù)必須是可迭代對(duì)象(如生成器函數(shù)),不能是普通列表(否則會(huì)一次性加載)。 - 禁用緩沖:
- 對(duì)于 Nginx 反向代理,需添加
response['X-Accel-Buffering'] = 'no',否則 Nginx 會(huì)緩沖數(shù)據(jù)直到生成器結(jié)束才推送。 - 對(duì)于 Apache,需配置
SetEnv no-gzip 1禁用壓縮緩沖。
- 對(duì)于 Nginx 反向代理,需添加
- 異常處理:生成器中如果出現(xiàn)異常,響應(yīng)會(huì)中斷,建議添加 try-except:
def stream_generator(): try: for i in range(5): time.sleep(1) yield f"第 {i+1} 塊數(shù)據(jù)\n" except Exception as e: yield f"出錯(cuò)了:{str(e)}\n" - 不支持某些中間件:部分 Django 中間件(如
GZipMiddleware)會(huì)緩沖響應(yīng),導(dǎo)致流式失效,需排除這些中間件。
總結(jié)
StreamingHttpResponse核心是通過(guò)生成器逐塊返回?cái)?shù)據(jù),避免一次性加載大量數(shù)據(jù)到內(nèi)存,適合大文件、實(shí)時(shí)數(shù)據(jù)場(chǎng)景。- 使用時(shí)需注意禁用緩沖(尤其是反向代理層),否則流式效果會(huì)失效。
- 不同場(chǎng)景需配置對(duì)應(yīng)的
Content-Type(如文件下載用application/octet-stream,SSE 用text/event-stream)。
補(bǔ)充:URL 配置(確保視圖可訪問(wèn))
在 urls.py 中添加路由:
from django.urls import path
from .views import StreamView, LargeFileDownloadView, SSEView
urlpatterns = [
path('stream/', StreamView.as_view(), name='stream'),
path('download-large-file/', LargeFileDownloadView.as_view(), name='download'),
path('sse/', SSEView.as_view(), name='sse'),
]
到此這篇關(guān)于Django使用StreamingHttpResponse實(shí)現(xiàn)流式響應(yīng)的實(shí)現(xiàn)示例的文章就介紹到這了,更多相關(guān)Django流式響應(yīng)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用python-cv2實(shí)現(xiàn)Harr+Adaboost人臉識(shí)別的示例
這篇文章主要介紹了使用python-cv2實(shí)現(xiàn)Harr+Adaboost人臉識(shí)別的示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-10-10
python使用tcp實(shí)現(xiàn)局域網(wǎng)內(nèi)文件傳輸
這篇文章主要介紹了python使用tcp實(shí)現(xiàn)局域網(wǎng)內(nèi)文件傳輸,文件包括文本,圖片,視頻等,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-07-07
Python處理圖像并生成JSONL元數(shù)據(jù)文件
JSONL是一種輕量級(jí)的數(shù)據(jù)序列化格式,由一系列獨(dú)立的?JSON?對(duì)象組成,本文主要為大家介紹了Python如何處理圖像并生成JSONL元數(shù)據(jù)文件,感興趣的可以了解下2025-05-05
提高Python生產(chǎn)力的五個(gè)Jupyter notebook插件
Jupyter Notebook 因其可用性和實(shí)用性而成為數(shù)據(jù)分析和機(jī)器學(xué)習(xí)模型領(lǐng)域最流行的 IDE,它也是很多數(shù)據(jù)初學(xué)者的首選 IDE。它最具特色的是,擁有豐富的插件、擴(kuò)展數(shù)據(jù)處理能力和提升工作效率2021-11-11
pandas 數(shù)據(jù)索引與選取的實(shí)現(xiàn)方法
這篇文章主要介紹了pandas 數(shù)據(jù)索引與選取的實(shí)現(xiàn)方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-06-06
Pytorch基本變量類型FloatTensor與Variable用法
今天小編就為大家分享一篇Pytorch基本變量類型FloatTensor與Variable用法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-01-01

