FastAPI StreamingResponse 與 FileResponse

當處理大型檔案或需要即時回傳資料時,我們不能一次將所有內容讀入記憶體再回傳,這時就需要使用串流 (Streaming) 或專用的檔案回應 (File Response)

StreamingResponse (串流回應)

StreamingResponse 接受一個生成器 (Generator) 或非同步生成器。它會邊讀邊傳,非常適合處理大型 CSV、日誌檔案或即時產生的內容。

import io
from fastapi import FastAPI
from fastapi.responses import StreamingResponse

app = FastAPI()

def fake_video_streamer():
    for i in range(10):
        yield b"some fake video bytes"

@app.get("/video")
async def main():
    return StreamingResponse(fake_video_streamer(), media_type="video/mp4")

傳回大型內容

範例:建立一個虛擬的大型檔案。

def generate_large_data():
    for i in range(1000):
        yield f"some data line {i}\n"

@app.get("/large-data")
async def get_large_data():
    return StreamingResponse(generate_large_data())

FileResponse (檔案下載)

FileResponse 是提供檔案服務的最佳方式。它能有效率地回傳磁碟上的檔案,並處理 HTTP 的範圍請求 (Range requests, 常用於影音播放)。

from fastapi import FastAPI
from fastapi.responses import FileResponse

app = FastAPI()

@app.get("/download/{file_id}")
async def download_file(file_id: str):
    file_path = f"files/{file_id}.pdf"

    # media_type 會自動判斷,也可以手動指定
    # filename 設定後,瀏覽器會將其視為下載檔案
    return FileResponse(
        path=file_path,
        filename=f"user_guide_{file_id}.pdf"
    )

參數說明

  • path: 檔案在伺服器磁碟上的完整路徑。
  • filename: 瀏覽器下載時顯示的預設檔名。
  • media_type: MIME 類型。如果沒設定,FastAPI 會嘗試根據副檔名判斷。

總結

  • StreamingResponse: 用於串流回傳資料,避免佔用大量記憶體。
  • FileResponse: 用於將預先存在的檔案回傳給使用者。
  • 這兩種回應方式能極大提升系統在處理大數據時的效率與穩定性。