【FastAPI】 响应类型详解:从默认 JSON 到自定义响应

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 的重要知识点"
    }
相关推荐
企业数字化笔记2 分钟前
AI工具参数很多怎么办?预设、表单校验、危险参数与配置审计
java·spring boot·python·音视频
2601_962885721 小时前
如何用 Python 计算 BBI 多空指标?
开发语言·python
必须得开心呀1 小时前
为什么 python-docx 打不开加密的 .docx,Word COM 却能打开
python·word
VidDown1 小时前
上传 2GB 文件别让 Django 接:分片上传、对象存储直传与秒传
python·django·音视频·状态模式·实时音视频·视频编解码·视频
打工仔折腾 AI1 小时前
FaceFusion本地换脸实战:Windows整合包、模型选择与遮罩调参记录
人工智能·windows·后端·python·深度学习·性能优化·ai agent 实战
yi0111 小时前
DAY24: LeetCode 167:两数之和 II|从暴力枚举到左右双指针
笔记·python·算法·leetcode·二分查找·双指针
kimnoic1 小时前
Python常用命令提示符使用方法详解
开发语言·python
用户7624117567052 小时前
第五章 字符串及正则表达式
python
天天被压力2 小时前
【别再到处找免费股票数据API了:官方204个接口,32篇一次讲透 #25】北交所财务技术指标难搞?12个接口,报表+MACD全拿
java·人工智能·python
Είναι η κοπέλα2 小时前
模型量化完全指南:GGUF、GPTQ、AWQ 怎么选
人工智能·pytorch·python