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 cleanup_interval = settings.cleanup_interval_seconds cleaner = FileCleaner(save_dir, retention_hours, cleanup_interval) @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 )