FastAPI 静态文件服务详解
文章目录
FastAPI 不仅能构建 API 接口,还内置了对静态文件服务的支持。通过 StaticFiles,你可以轻松地将图片、CSS、JavaScript 或任意静态资源目录挂载到应用中,像传统 Web 服务器一样对外提供文件访问。
为什么需要静态文件服务
大多数 Web 应用除了 API 接口外,还需要直接向浏览器提供静态资源。比如:
- 前端打包后的 HTML、CSS、JS 文件
- 用户上传的头像、附件
- 接口文档引用的图片资源
- favicon 等站点图标
FastAPI 基于 Starlette,而 Starlette 提供了 StaticFiles 这个 ASGI 应用,可以直接挂载到 FastAPI 的路由体系中使用。
基础用法:挂载目录
StaticFiles 位于 starlette.staticfiles(也可从 fastapi.staticfiles 导入),使用 app.mount() 将其挂载到指定路径前缀下:
1 | from fastapi import FastAPI |
目录结构假设如下:
1 | project/ |
挂载后访问规则:
| 请求路径 | 对应本地文件 |
|---|---|
/static/logo.png |
static/logo.png |
/static/style.css |
static/style.css |
/static/images/banner.jpg |
static/images/banner.jpg |
注意:app.mount() 挂在指定路径下的 子应用,该路径本身不会被 FastAPI 的路由处理 — 完全由 StaticFiles 接管。
关键参数详解
StaticFiles 构造函数的常用参数:
1 | StaticFiles( |
html 参数
当 html=True 时,访问 index.html 等文件会以 text/html Content-Type 返回,适合挂载前端 SPA 的打包产物:
1 | app.mount("/", StaticFiles(directory="frontend/dist", html=True), name="frontend") |
packages 参数
用于引用已安装 Python 包内的静态资源:
1 | app.mount("/static", StaticFiles(packages=[("my_package", "static")]), name="static") |
这会查找 my_package 包内的 static 子目录。
挂载顺序与路由优先级
挂载路径优先于路由。Starlette 按注册顺序匹配,一旦某个 mount 路径前缀命中,后续路由就不会再检查。错误示例:
1 | app = FastAPI() |
正确做法是 API 路由注册在前,静态文件挂载在后(或者用不同路径前缀):
1 | app = FastAPI() |
或者更清晰的方式 — 使用不同前缀:
1 | app = FastAPI() |
运行时动态添加静态目录
如果需要根据运行时条件挂载不同目录(如按用户区分的上传目录),可以在路由层手动构造 StaticFiles 应用后挂载:
1 | from fastapi import FastAPI |
如果需要更复杂的逻辑(如按用户 id 分流),则不适合用 mount,应改用 FileResponse 在路由中手动处理文件返回。
配合 FileResponse 精确控制
对于需要权限校验或动态路径的单个文件返回,使用 FileResponse 而非全局挂载:
1 | from fastapi import FastAPI |
FileResponse 支持的关键参数:
| 参数 | 说明 |
|---|---|
path |
文件路径 |
filename |
下载时显示的文件名(触发 Content-Disposition) |
media_type |
显式指定 MIME 类型 |
headers |
自定义响应头字典 |
挂载多个静态目录
FastAPI 支持同时挂载多个静态目录到不同路径:
1 | from fastapi import FastAPI |
各挂载点互不干扰,各自管理自己的目录。
生产环境注意事项
StaticFiles 使用 Python 的 aiofiles 做异步文件 I/O,在开发和小规模场景足够。但在高并发生产环境中,建议:
- 由 Nginx / Caddy 等反向代理直接处理静态文件请求
- FastAPI 只处理 API 逻辑,静态文件路径在反向代理层拦截
Nginx 配置示例片段:
1 | server { |
总结
| 场景 | 推荐方案 |
|---|---|
| 全局静态资源目录 | app.mount("/static", StaticFiles(...)) |
| 前端 SPA 部署 | app.mount("/", StaticFiles(..., html=True)) |
| 需要权限控制的文件下载 | 路由中使用 FileResponse |
| 高并发生产环境 | Nginx 直接处理,FastAPI 只做 API |
掌握 StaticFiles 和 FileResponse 两种方式,就能灵活应对从开发到生产的不同静态文件需求。