FastAPI 响应类型详解:从默认 JSON 到自定义响应(HTML/文件/流/重定向)
一、FastAPI 响应机制概述
FastAPI 默认会将路径操作函数返回的 Python 对象(如 dict、list、Pydantic Model)自动转换为 JSON 格式 ,并通过 JSONResponse 返回客户端。
转换依赖
jsonable_encoder,无需手动序列化。
python
return {"message": "Hello World"} # 自动转为 JSON
但若需返回非 JSON 数据(如 HTML、文件、流、纯文本等),必须显式指定响应类型。
二、响应类型设置方式(共 6 种)
方式一:在 @app.get() 装饰器中设置 response_class
适用场景 :固定返回类型,如
HTML、纯文本、文件(非动态流式)
python
from fastapi import FastAPI
from fastapi.responses import HTMLResponse, PlainTextResponse, FileResponse
app = FastAPI()
@app.get("/", response_class=HTMLResponse)
async def root():
return "<h1>这是一级标题</h1>"
| 响应类型 | response_class |
用途 |
|---|---|---|
HTMLResponse |
HTMLResponse |
返回 HTML 内容(如网页) |
PlainTextResponse |
PlainTextResponse |
返回纯文本(不含 HTML 标签) |
FileResponse |
FileResponse |
返回文件下载(如图片、txt、pdf) |
示例:纯文本响应
python
@app.get("/text", response_class=PlainTextResponse)
async def get_text():
return "这是纯文本"
示例:文件下载
python
@app.get("/file/txt", response_class=FileResponse)
async def get_file():
return "./files/1.txt"
💡 注意:
FileResponse会自动设置Content-Disposition: attachment,触发下载。
方式二:直接返回响应对象(推荐用于动态响应)
适用场景:文件流、图片、自定义 MIME 类型、重定向、流式响应
返回图片(FileResponse)
python
@app.get("/file/picture")
async def get_picture():
return FileResponse("./files/1.png")
自动设置
Content-Type: image/png
流式响应(StreamingResponse)
python
from fastapi.responses import StreamingResponse
@app.get("/stream")
async def get_stream():
def iter_file():
with open("./files/1.png", "rb") as f:
while chunk := f.read(1024):
yield chunk
return StreamingResponse(iter_file(), media_type="image/png")
使用生成器函数模拟流式传输,适用于大文件、视频流等。
自定义 MIME 类型与文件名
python
@app.get("/file/download")
async def download_file():
return FileResponse(
path="./files/1.txt",
media_type="text/plain", # 自定义 MIME 类型
filename="news.txt" # 下载时的文件名
)
可通过
filename设置下载后文件名,打破原文件名限制。
方式三:使用 RedirectResponse(重定向)
python
from fastapi.responses import RedirectResponse
@app.get("/redirect")
async def redirect_to_home():
return RedirectResponse(url="/")
浏览器将跳转到
/地址,返回302状态码。
重定向到外链(如百度)
python
@app.get("/to-baidu")
async def to_baidu():
return RedirectResponse(url="https://www.baidu.com")
方式四:自定义响应数据格式(response_model + Pydantic)
用 Pydantic 模型定义 API 返回结构,实现类型安全与文档自动生成。
步骤 1:定义 Pydantic 模型
python
from pydantic import BaseModel
class News(BaseModel):
id: int
title: str
content: str
步骤 2:在路由中启用 response_model
python
@app.get("/news/{id}", response_model=News)
async def get_news(id: int):
return {
"id": id,
"title": "这是新闻标题",
"content": "这是新闻内容"
}
如果返回数据不符合
News模型结构 → FastAPI 会返回422错误Swagger UI 会根据
response_model生成响应示例
三、FastAPI 响应类型总结表
| 响应类型 | 用途 | 何时使用 | 示例 |
|---|---|---|---|
JSONResponse(默认) |
返回 JSON 数据 | 一般 API 接口 | return {"msg": "ok"} |
HTMLResponse |
返回 HTML 内容 | 页面渲染、内嵌 HTML | response_class=HTMLResponse |
PlainTextResponse |
返回纯文本 | 日志、简单信息 | response_class=PlainTextResponse |
FileResponse |
文件下载 | 下载 PDF、TXT、图片 | return FileResponse("./file.txt") |
StreamingResponse |
流式响应 | 大文件、视频、音频流 | StreamingResponse(generator, media_type="video/mp4") |
RedirectResponse |
重定向 | 跳转页面、登录后跳转 | return RedirectResponse(url="/") |
四、易错点 & 注意事项
| 易错点 | 说明 | 解决方案 |
|---|---|---|
❌ response_class 放在函数外 |
导致 AttributeError |
必须在装饰器里写 response_class=... |
❌ FileResponse 路径写错 |
文件找不到,返回 404 | 使用 os.path 或 Path 拼接路径 |
| ❌ 流式响应未使用生成器 | 报错或无法传输 | 用 def iter_func(): yield chunk |
❌ response_model 返回字段类型不匹配 |
返回 422 错误 |
保证数据完全符合模型结构 |
❌ 忘记 import 响应类 |
编译错误 | 一定要导入:from fastapi.responses import ... |
五、完整代码示例(可直接运行)
python
from fastapi import FastAPI
from fastapi.responses import (
HTMLResponse,
PlainTextResponse,
FileResponse,
StreamingResponse,
RedirectResponse
)
from pydantic import BaseModel
import os
app = FastAPI()
# 1. 默认 JSON 响应(自动)
@app.get("/")
async def root():
return {"message": "Hello World"}
# 2. HTML 响应(固定类型)
@app.get("/html", response_class=HTMLResponse)
async def get_html():
return "<h1>这是网页标题</h1>"
# 3. 纯文本响应
@app.get("/text", response_class=PlainTextResponse)
async def get_text():
return "这是纯文本内容"
# 4. 文件下载(自动触发下载)
@app.get("/file/download")
async def get_txt():
return FileResponse("./files/1.txt", filename="news.txt")
# 5. 图片响应
@app.get("/image")
async def get_image():
return FileResponse("./files/1.png")
# 6. 流式响应(支持大文件)
@app.get("/stream")
async def stream_video():
def iter_file():
with open("./files/1.png", "rb") as f:
while chunk := f.read(1024):
yield chunk
return StreamingResponse(iter_file(), media_type="image/png")
# 7. 重定向
@app.get("/redirect")
async def redirect_home():
return RedirectResponse(url="/")
# 8. 自定义响应数据格式(Pydantic + response_model)
class News(BaseModel):
id: int
title: str
content: str
@app.get("/news/{id}", response_model=News)
async def get_news(id: int):
return {
"id": id,
"title": "FastAPI 响应类型详解",
"content": "学习 FastAPI 的重要知识点"
}