FastAPI 静态文件
FastAPI 静态文件学习笔记一、基本用法 —StaticFiles1. 挂载静态文件目录fromfastapiimportFastAPIfromfastapi.staticfilesimportStaticFiles appFastAPI()# 将 ./static 目录挂载到 /static 路径app.mount(/static,StaticFiles(directorystatic),namestatic)目录结构project/ ├── main.py └── static/ ├── css/ │ └── style.css ├── js/ │ └── app.js └── images/ └── logo.png访问方式http://localhost:8000/static/css/style.css http://localhost:8000/static/js/app.js http://localhost:8000/static/images/logo.png2. 参数说明参数类型默认值说明directorystr/Path必填静态文件目录路径htmlboolFalse是否启用 HTML 模式check_dirboolTrue启动时检查目录是否存在二、HTML 模式1. 启用 HTML 模式app.mount(/,StaticFiles(directorystatic,htmlTrue),namestatic)HTML 模式行为请求路径文件存在情况响应/index.html存在返回index.html/aboutabout.html存在返回about.html/about/about/index.html存在返回about/index.html/style.cssstyle.css存在返回style.css/missing无匹配文件4042. 典型用途 — 托管 SPA 前端# Vue / React 构建产物app.mount(/,StaticFiles(directorydist,htmlTrue),namespa)dist/ ├── index.html ├── assets/ │ ├── index.abc123.js │ └── index.def456.css └── favicon.ico注意SPA 的前端路由如/about、/user/1需要服务端统一返回index.htmlhtmlTrue只处理.html文件匹配不支持 SPA fallback。完整 SPA 托管方案见第五节。三、挂载位置与路由优先级1.app.mount的特性mount创建的是一个子应用会匹配该路径下的所有请求不再经过主应用的路由匹配appFastAPI()app.get(/static/data)# ← 永远不会被访问到asyncdefget_data():return{data:hello}app.mount(/static,StaticFiles(directorystatic),namestatic)# /static/* 的所有请求都被 StaticFiles 拦截2. 正确的挂载顺序appFastAPI()# ① 先注册 API 路由app.get(/api/data)asyncdefget_data():return{data:hello}# ② 最后挂载静态文件避免覆盖 API 路由app.mount(/static,StaticFiles(directorystatic),namestatic)3. 挂载多个静态目录app.mount(/static,StaticFiles(directorystatic),namestatic)app.mount(/uploads,StaticFiles(directoryuploads),nameuploads)app.mount(/assets,StaticFiles(directoryassets),nameassets)四、在 Jinja2 模板中引用静态文件fromfastapiimportFastAPI,Requestfromfastapi.staticfilesimportStaticFilesfromfastapi.templatingimportJinja2Templates appFastAPI()app.mount(/static,StaticFiles(directorystatic),namestatic)templatesJinja2Templates(directorytemplates)app.get(/page)asyncdefpage(request:Request):returntemplates.TemplateResponse(page.html,{request:request})模板中引用!-- 使用 url_for 动态生成路径 --linkrelstylesheethref{{ url_for(static, path/css/style.css) }}scriptsrc{{ url_for(static, path/js/app.js) }}/scriptimgsrc{{ url_for(static, path/images/logo.png) }}altlogourl_for的第一个参数是mount时的name第二个参数path是文件在静态目录中的相对路径。五、SPA 前端托管完整方案Vue / React 等单页应用需要所有未匹配路径返回index.html方案一中间件 fallbackfromfastapiimportFastAPI,Requestfromfastapi.staticfilesimportStaticFilesfromfastapi.responsesimportFileResponse appFastAPI()# API 路由app.get(/api/data)asyncdefget_data():return{data:hello}# 静态资源js/css/imagesapp.mount(/assets,StaticFiles(directorydist/assets),nameassets)# SPA fallback未匹配的路由返回 index.htmlapp.get(/{full_path:path})asyncdefserve_spa(request:Request,full_path:str):returnFileResponse(dist/index.html)方案二自定义静态文件中间件importosfromfastapiimportFastAPI,Requestfromfastapi.responsesimportFileResponse,Responsefromstarlette.middleware.baseimportBaseHTTPMiddleware appFastAPI()DIST_DIRdistclassSPAMiddleware(BaseHTTPMiddleware):asyncdefdispatch(self,request:Request,call_next):responseawaitcall_next(request)# 如果路由返回 404 且是 HTML 请求返回 index.htmlifresponse.status_code404:acceptrequest.headers.get(accept,)iftext/htmlinaccept:index_pathos.path.join(DIST_DIR,index.html)ifos.path.exists(index_path):returnFileResponse(index_path)returnresponse app.add_middleware(SPAMiddleware)app.mount(/assets,StaticFiles(directoryf{DIST_DIR}/assets),nameassets)方案三纯静态挂载最简单appFastAPI()# API 路由app.get(/api/data)asyncdefget_data():return{data:hello}# 静态文件htmlTrue 自动处理 index.htmlapp.mount(/,StaticFiles(directorydist,htmlTrue),namespa)局限htmlTrue只在请求路径对应.html文件存在时返回不支持 SPA 的动态路由如/user/123。六、文件上传与静态文件服务结合importosimportuuidfromfastapiimportFastAPI,UploadFile,Filefromfastapi.staticfilesimportStaticFiles appFastAPI()UPLOAD_DIRuploadsos.makedirs(UPLOAD_DIR,exist_okTrue)app.post(/upload)asyncdefupload_file(file:UploadFileFile(...)):# 生成唯一文件名extos.path.splitext(file.filename)[1]filenamef{uuid.uuid4().hex}{ext}filepathos.path.join(UPLOAD_DIR,filename)# 保存文件withopen(filepath,wb)asf:contentawaitfile.read()f.write(content)return{filename:filename,url:f/uploads/{filename},}# 挂载上传目录app.mount(/uploads,StaticFiles(directoryUPLOAD_DIR),nameuploads)七、生产环境注意事项1. Nginx 反向代理直接服务静态文件生产环境建议由 Nginx 直接处理静态文件性能更好server { listen 80; server_name example.com; # Nginx 直接服务静态文件 location /static/ { alias /var/www/static/; expires 30d; add_header Cache-Control public, immutable; } # API 请求转发给 FastAPI location /api/ { proxy_pass http://127.0.0.1:8000; } }2. 缓存控制fromstarlette.responsesimportResponsefromfastapi.staticfilesimportStaticFilesclassCachedStaticFiles(StaticFiles):asyncdeflookup_path(self,path:str):full_path,stat_resultawaitsuper().lookup_path(path)ifstat_result:# 根据文件扩展名设置缓存ifpath.endswith((.js,.css,.woff2,.png,.jpg)):self.headers[Cache-Control]public, max-age31536000, immutableelse:self.headers[Cache-Control]public, max-age3600returnfull_path,stat_result app.mount(/static,CachedStaticFiles(directorystatic),namestatic)3. 目录安全风险防护措施目录遍历攻击StaticFiles默认禁止..路径敏感文件泄露不要将配置文件、.env放在静态目录上传恶意文件限制文件类型、重命名文件、隔离上传目录大文件消耗带宽Nginx 层限制请求体大小八、StaticFilesvs 其他方案方案适用场景性能灵活性StaticFiles开发环境、小型项目中低Nginx 直接服务生产环境高高CDN全球分发、高流量最高最高云存储OSS/S3用户上传文件、海量存储高高推荐开发环境 → StaticFiles零配置 生产环境 → Nginx 直接服务静态文件 CDN 加速 用户上传 → 云存储OSS / S3 CDN九、完整示例fromfastapiimportFastAPI,Request,UploadFile,Filefromfastapi.staticfilesimportStaticFilesfromfastapi.responsesimportFileResponseimportos,uuid appFastAPI()# ---- 目录准备 ----os.makedirs(static/css,exist_okTrue)os.makedirs(static/js,exist_okTrue)os.makedirs(uploads,exist_okTrue)# ---- API 路由 ----app.get(/api/hello)asyncdefhello():return{message:Hello, FastAPI!}app.post(/api/upload)asyncdefupload(file:UploadFileFile(...)):extos.path.splitext(file.filename)[1]filenamef{uuid.uuid4().hex}{ext}withopen(fuploads/{filename},wb)asf:f.write(awaitfile.read())return{url:f/uploads/{filename}}# ---- 静态文件挂载 ----app.mount(/static,StaticFiles(directorystatic),namestatic)app.mount(/uploads,StaticFiles(directoryuploads),nameuploads)# ---- SPA fallback放最后----app.get(/{full_path:path})asyncdefspa_fallback(request:Request,full_path:str):returnFileResponse(static/index.html)十、注意事项mount必须放在路由注册之后否则会拦截所有匹配路径的请求导致 API 路由不可达。目录必须存在默认check_dirTrue目录不存在会抛异常。启动前确保目录已创建。name参数的作用用于url_for反向生成 URL建议始终设置。开发 vs 生产StaticFiles适合开发生产环境推荐 Nginx / CDN。路径以/结尾访问目录路径时StaticFiles会自动查找index.html需htmlTrue。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2592936.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!