Spaces:
Running
Running
File size: 2,652 Bytes
9b53f70 91f1a3a 9b53f70 3370310 9b53f70 91f1a3a 9b53f70 00d2c12 9b53f70 e014541 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | """Endpoint dùng chung: trạng thái job, tải file kết quả."""
from __future__ import annotations
import os
from urllib.parse import quote
from fastapi import APIRouter, HTTPException
from fastapi.responses import FileResponse
from ..core.files import session_dir, delete_session
from ..core.jobs import jobs
router = APIRouter(prefix="/api", tags=["common"])
@router.delete("/sessions/{sid}")
def drop_session(sid: str):
"""Xoá phiên tạm sau khi user đã tải kết quả về máy (không bắt buộc)."""
return {"deleted": delete_session(sid), "session": sid}
@router.get("/jobs/{job_id}")
def job_status(job_id: str):
job = jobs.get(job_id)
if not job:
raise HTTPException(404, "job không tồn tại")
return job.to_dict()
@router.get("/queue/stats")
def queue_stats():
"""Số liệu hàng đợi: số job đang chạy/chờ theo loại + tổng job trong bộ nhớ."""
return jobs.stats()
@router.post("/jobs/{job_id}/cancel")
def job_cancel(job_id: str):
jobs.cancel(job_id)
return {"ok": True}
@router.get("/sessions/{sid}/inputs")
def list_inputs(sid: str):
"""Liệt kê video trong thư mục inputs của phiên (dùng khi đẩy từ Down list)."""
d = os.path.join(session_dir(sid), "inputs")
if not os.path.isdir(d):
return {"session": sid, "files": []}
out = []
for name in sorted(os.listdir(d)):
full = os.path.join(d, name)
if os.path.isfile(full):
out.append({
"file": f"inputs/{name}",
"name": name,
"size": os.path.getsize(full),
"url": f"/api/files/{sid}/inputs/{quote(name)}",
})
return {"session": sid, "files": out}
@router.get("/files/{sid}/{path:path}")
def get_file(sid: str, path: str):
base = os.path.abspath(session_dir(sid))
# Chấp cả "/" lẫn "\" trong path (Windows) -> chuẩn hoá trước khi nối.
rel = path.replace("\\", "/").strip("/")
full = os.path.abspath(os.path.join(base, *rel.split("/")))
# Phải nằm trong phiên VÀ là FILE thật: trỏ vào THƯ MỤC thì FileResponse
# ném lỗi 500, trong khi đúng nghĩa là 404.
if not full.startswith(base) or not os.path.isfile(full):
raise HTTPException(404, "file không tồn tại")
# inline (KHÔNG attachment) -> trình duyệt render video/ảnh trực tiếp trong <video>.
# Nút tải vẫn hoạt động nhờ thuộc tính `download` phía frontend.
return FileResponse(full, filename=os.path.basename(full),
content_disposition_type="inline")
|