japi/apps/jfile/app.py
jingrow 419744686f feat(jfile): 添加CORS响应头支持第三方前端下载图片
- 添加HTTP中间件为/files路径响应添加CORS响应头
- 支持Access-Control-Allow-Origin、Access-Control-Allow-Methods和Access-Control-Expose-Headers
- 添加Content-Disposition头让浏览器直接下载而不是打开图片
- 统一处理OPTIONS预检请求
- 优化性能:提前返回非目标请求
2025-11-21 01:44:02 +08:00

69 lines
2.1 KiB
Python

import uvicorn
from fastapi import FastAPI, Request
from fastapi.staticfiles import StaticFiles
from fastapi.responses import Response
from file_cleaner import FileCleaner
from settings import settings
import asyncio
import os
app = FastAPI(
title="www",
description="公共静态资源访问服务",
version="1.0.0"
)
# 添加中间件,为静态文件响应添加 CORS 响应头和下载头
@app.middleware("http")
async def add_cors_headers(request: Request, call_next):
# 只处理 /files 路径的请求,提前返回提高效率
if not request.url.path.startswith("/files"):
return await call_next(request)
# 处理 OPTIONS 预检请求
if request.method == "OPTIONS":
return Response(
headers={
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET, OPTIONS",
"Access-Control-Expose-Headers": "Content-Disposition"
}
)
# 处理 GET 请求
response = await call_next(request)
# 添加 CORS 响应头
response.headers["Access-Control-Allow-Origin"] = "*"
response.headers["Access-Control-Allow-Methods"] = "GET, OPTIONS"
response.headers["Access-Control-Expose-Headers"] = "Content-Disposition"
# 添加 Content-Disposition 头,让浏览器下载而不是打开
if "Content-Disposition" not in response.headers:
filename = os.path.basename(request.url.path)
if filename:
response.headers["Content-Disposition"] = f'attachment; filename="{filename}"'
return response
# 挂载静态文件目录
app.mount("/files", StaticFiles(directory="files"), name="files")
# 注册文件定时清理任务
save_dir = "files"
retention_hours = settings.file_retention_hours
cleaner = FileCleaner(save_dir, retention_hours)
@app.on_event("startup")
async def startup_event():
asyncio.create_task(cleaner.periodic_cleanup())
if __name__ == "__main__":
import uvicorn
uvicorn.run(
"app:app",
host=settings.host,
port=settings.port,
reload=settings.debug
)