手把手搞定FastAPI静态文件:安全、上传与访问
✨ 目录一览- 起步为什么需要处理静态文件- FastAPI的“文件管家”StaticFiles- 给静态文件加把“锁”安全设置详解- ⭐ 小图标大学问Favicon的处理- 不止于图片媒体文件的上传与响应- 实战演练一个完整的示例应用 起步为什么需要处理静态文件你的API很酷但用户访问http://localhost:8000/logo.png却得到404这是因为FastAPI默认是个纯粹的API框架它不会自动提供像图片、CSS、JavaScript这样的静态文件。静态文件是那些内容固定、不经常改变的文件。它们对于构建一个完整的Web应用或API文档门户至关重要。 FastAPI的“文件管家”StaticFiles引入StaticFiles你就能轻松搭建一个文件服务器。其核心三步法- 导入from fastapi.staticfiles import StaticFiles- 挂载将URL路径“挂载”到一个实际目录。- 应用使用app.mount方法。from fastapi import FastAPI from fastapi.staticfiles import StaticFiles app FastAPI() # 将路径 “/static” 映射到项目下的 “static” 目录 app.mount(/static, StaticFiles(directorystatic), namestatic)理解“挂载”它意味着所有访问/static/*的请求都会由StaticFiles实例去./static目录下查找对应文件。它不是API路由而是一个独立的子应用。 给静态文件加把“锁”安全设置详解开放文件访问是危险的错误的配置可能导致敏感文件泄露如.env、.git目录。1.限制目录访问范围永远不要将根目录“/”挂载到静态文件服务。务必使用一个独立的、权限明确的子目录如static、assets。2.使用“htmlTrue”安全地提供HTML如果你想提供单页应用如Vue/React构建的产物可以设置htmlTrue并让index.html作为目录的默认页。# 安全地提供前端构建产物目录 app.mount(/app, StaticFiles(directory./frontend/dist, htmlTrue), namespa_app)注意htmlTrue只对提供前端SPA友好它本身并不是一个安全漏洞。真正的安全在于对directory参数的控制。⭐ 小图标大学问Favicon的处理浏览器会自动请求/favicon.ico。如果你没处理日志里就会堆满404错误显得不专业。最简单的方法直接把它当成一个静态文件处理。# 方法为favicon.ico单独设置一个路径路由或将它放在static目录 from fastapi.responses import FileResponse app.get(/favicon.ico) async def favicon(): return FileResponse(static/favicon.ico)这能一劳永逸地消除那个烦人的404请求。 不止于图片媒体文件的上传与响应静态文件是“读”媒体文件则常涉及“写”上传。FastAPI处理上传非常优雅。-上传使用File和UploadFile。-存储使用shutil或aiofiles写入特定目录如media/。-访问再次借助StaticFiles挂载media/目录。from fastapi import File, UploadFile import shutil import os UPLOAD_DIR media os.makedirs(UPLOAD_DIR, exist_okTrue) app.post(/upload/image/) async def upload_image(file: UploadFile File(...)): file_path os.path.join(UPLOAD_DIR, file.filename) with open(file_path, wb) as buffer: shutil.copyfileobj(file.file, buffer) return {filename: file.filename, url: f/media/{file.filename}} # 挂载上传的媒体文件目录 app.mount(/media, StaticFiles(directorymedia), namemedia) 实战演练一个完整的示例应用下面是一个整合了上述所有知识点的完整main.py文件复制即可运行体验。from fastapi import FastAPI, File, UploadFile, Request from fastapi.staticfiles import StaticFiles from fastapi.responses import FileResponse, HTMLResponse import shutil import os from pathlib import Path app FastAPI() # 1. 创建必要的目录 static_dir Path(static) media_dir Path(media) static_dir.mkdir(exist_okTrue) media_dir.mkdir(exist_okTrue) # 2. 挂载静态文件目录存放CSSJS预置图片 app.mount(/static, StaticFiles(directorystatic_dir), namestatic) # 3. 挂载媒体文件目录存放用户上传的图片 app.mount(/media, StaticFiles(directorymedia_dir), namemedia) # 4. 处理favicon请求 app.get(/favicon.ico, include_in_schemaFalse) async def get_favicon(): # 假设你的favicon.ico放在static目录下 return FileResponse(static_dir / favicon.ico) # 5. 文件上传接口 app.post(/upload/) async def create_upload_file(file: UploadFile File(...)): # 保存上传的文件到media目录 save_path media_dir / file.filename with save_path.open(wb) as buffer: shutil.copyfileobj(file.file, buffer) # 返回文件的访问URL return {url: f/media/{file.filename}} # 6. 一个简单的前端页面用于演示和测试上传 app.get(/, response_classHTMLResponse) async def main(): return html head titleFastAPI静态文件演示/title /head body h2上传图片测试/h2 form action/upload/ enctypemultipart/form-data methodpost input namefile typefile input typesubmit /form br h3尝试访问/h3 ul lia href/static/example.txt预置的静态文件 (/static/example.txt)/a/li li上传后访问code/media/[你的文件名]/code/li /ul /body /html if __name__ __main__: import uvicorn uvicorn.run(app, host0.0.0.0, port8000)运行后访问http://localhost:8000即可体验上传和访问文件。记得先在static/目录下放个example.txt文件。