支持fastapi服务
This commit is contained in:
72
api/routers/files.py
Normal file
72
api/routers/files.py
Normal file
@@ -0,0 +1,72 @@
|
||||
"""
|
||||
File service endpoints
|
||||
|
||||
Provides access to generated files (videos, images, audio).
|
||||
"""
|
||||
|
||||
from pathlib import Path
|
||||
from fastapi import APIRouter, HTTPException
|
||||
from fastapi.responses import FileResponse
|
||||
from loguru import logger
|
||||
|
||||
router = APIRouter(prefix="/files", tags=["Files"])
|
||||
|
||||
|
||||
@router.get("/{file_path:path}")
|
||||
async def get_file(file_path: str):
|
||||
"""
|
||||
Get file by path
|
||||
|
||||
Serves files from the output directory only.
|
||||
|
||||
- **file_path**: File name or path (e.g., "abc123.mp4" or "subfolder/abc123.mp4")
|
||||
|
||||
Returns file for download or preview.
|
||||
"""
|
||||
try:
|
||||
# Automatically prepend "output/" to the path
|
||||
full_path = f"output/{file_path}"
|
||||
abs_path = Path.cwd() / full_path
|
||||
|
||||
if not abs_path.exists():
|
||||
raise HTTPException(status_code=404, detail=f"File not found: {file_path}")
|
||||
|
||||
if not abs_path.is_file():
|
||||
raise HTTPException(status_code=400, detail=f"Path is not a file: {file_path}")
|
||||
|
||||
# Security: only allow access to output directory
|
||||
try:
|
||||
rel_path = abs_path.relative_to(Path.cwd())
|
||||
if not str(rel_path).startswith("output"):
|
||||
raise HTTPException(status_code=403, detail="Access denied: only output directory is accessible")
|
||||
except ValueError:
|
||||
raise HTTPException(status_code=403, detail="Access denied")
|
||||
|
||||
# Determine media type
|
||||
suffix = abs_path.suffix.lower()
|
||||
media_types = {
|
||||
'.mp4': 'video/mp4',
|
||||
'.mp3': 'audio/mpeg',
|
||||
'.wav': 'audio/wav',
|
||||
'.png': 'image/png',
|
||||
'.jpg': 'image/jpeg',
|
||||
'.jpeg': 'image/jpeg',
|
||||
'.gif': 'image/gif',
|
||||
}
|
||||
media_type = media_types.get(suffix, 'application/octet-stream')
|
||||
|
||||
# Use inline disposition for browser preview
|
||||
return FileResponse(
|
||||
path=str(abs_path),
|
||||
media_type=media_type,
|
||||
headers={
|
||||
"Content-Disposition": f'inline; filename="{abs_path.name}"'
|
||||
}
|
||||
)
|
||||
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
logger.error(f"File access error: {e}")
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
Reference in New Issue
Block a user