""" دانلود فایل اکسل تولیدشده از خروجی جدول (Table Engine). فایل‌ها در پوشه temp پروژه ذخیره می‌شوند و از طریق این endpoint قابل دانلود هستند. """ import os import re from fastapi import APIRouter, HTTPException from starlette.responses import FileResponse from config import conf from core.app import app from core.utils.router import generate_router router = generate_router("download", auth_dependencies=False, version="v2") _tag_base = ["download"] _pre = conf.server.prefix_url.replace("v1", "v2") def _excel_temp_dir(): return os.path.join(os.getcwd(), "temp") def _safe_excel_filename(name: str) -> bool: """فقط نام فایل اکسلی با فرمت uuid.xlsx (۳۲ کاراکتر hex + .xlsx) مجاز است.""" return bool(re.match(r"^[a-f0-9]{32}\.xlsx$", name)) @router.get("/excel/{filename}", tags=_tag_base) async def download_excel(filename: str): """ دانلود فایل اکسل با نام بازگردانده‌شده از API لیست (فیلد path). مثال: بعد از درخواست خروجی اکسل، در پاسخ path مثلاً «abc123...xlsx» می‌آید؛ برای دانلود: GET /v2/download/excel/abc123....xlsx """ if not _safe_excel_filename(filename): raise HTTPException(status_code=400, detail="نام فایل نامعتبر است.") file_path = os.path.join(_excel_temp_dir(), filename) if not os.path.isfile(file_path): raise HTTPException(status_code=404, detail="فایل یافت نشد یا منقضی شده است.") return FileResponse( file_path, media_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", filename=filename, ) app.include_router(router)