from __future__ import annotations from fastapi import APIRouter, Depends, Query, Request from fastapi.responses import StreamingResponse from sqlalchemy import select from sqlalchemy.orm import Session from iti.auth import require_user from iti.db import get_db from iti.exceptions import BizError from iti.responses import ok from iti.storage import StorageManager from iti_system.models import SysFile from iti_system.services import dump_file, get_or_404 router = APIRouter(prefix="/file", tags=["common.file"]) @router.get("/share/{share_code}") def share_file(share_code: str, password: str | None = Query(default=None), db: Session = Depends(get_db)): item = db.scalar(select(SysFile).where(SysFile.share_code == share_code)) if item is None: raise BizError("分享不存在", code=404) if item.share_password and item.share_password != password: raise BizError("分享密码错误", code=403) item.share_count += 1 db.commit() return ok(dump_file(item)) @router.get("/share/{share_code}/download") def share_download(share_code: str, password: str | None = Query(default=None), db: Session = Depends(get_db)): item = db.scalar(select(SysFile).where(SysFile.share_code == share_code)) if item is None: raise BizError("分享不存在", code=404) if item.share_password and item.share_password != password: raise BizError("分享密码错误", code=403) item.share_count += 1 db.commit() return ok(dump_file(item)) @router.get("/{file_id}/download", dependencies=[Depends(require_user)]) def download_file(file_id: str, request: Request, db: Session = Depends(get_db)): item = get_or_404(db, SysFile, file_id, "文件不存在") storage = StorageManager.get_storage( item.storage_type, config=request.app.state.config.file_storage, base_dir=request.app.state.config.base_dir, ) stream = storage.download(item.file_key) return StreamingResponse( stream, media_type=item.mime_type or "application/octet-stream", headers={"Content-Disposition": f'attachment; filename="{item.filename}"'}, ) @router.get("/{file_id}/preview", dependencies=[Depends(require_user)]) def preview_file(file_id: str, db: Session = Depends(get_db)): return ok(dump_file(get_or_404(db, SysFile, file_id, "文件不存在"))) @router.get("/{file_id}/thumbnail", dependencies=[Depends(require_user)]) def thumbnail_file(file_id: str, w: int = 200, h: int = 200, mode: str = "fit", db: Session = Depends(get_db)): item = get_or_404(db, SysFile, file_id, "文件不存在") data = dump_file(item) data.update({"width": w, "height": h, "mode": mode}) return ok(data)