ComfyUI-Ranking-API / media_proxy_service.py
ZHIWEI666's picture
Upload 11 files
e12a676 verified
Raw History Blame Contribute Delete
3.49 kB
"""公开媒体读取服务;仅代理既有允许目录与扩展名,不处理工作流下载。"""
import logging
import mimetypes
import os
import time
import urllib.parse
import uuid
from fastapi import HTTPException
from fastapi.responses import JSONResponse
from proxy_download_work import ProxyDownloadWork
_public_media_work = ProxyDownloadWork(16)
public_media_endpoint = _public_media_work.endpoint
start_public_media = _public_media_work.start
stop_public_media = _public_media_work.stop
close_public_media = _public_media_work.close
logger = logging.getLogger("ComfyUI-Ranking")
def read_public_media(url=None, path=None, *, store, download, file_response, error_response):
"""公开媒体服务:使用服务凭据读取既有允许目录中的媒体"""
# 兼容处理:如果本地发来的是已经被污染的老版本 HF 直链,我们自动将其转换为相对路径
if url and url.startswith("https://huggingface.co/datasets/"):
try:
path = url.split("resolve/main/")[-1]
path = urllib.parse.unquote(path)
except Exception:
raise HTTPException(status_code=400, detail="无效的 HF 原链接格式")
if not path:
raise HTTPException(status_code=400, detail="缺少路径参数")
# 🛡️ 路径穿越防护:禁止包含 .. 和绝对路径
if ".." in path or path.startswith("/"):
raise HTTPException(status_code=400, detail="非法路径")
# 🛡️ 绝对的安全红线:限制只能代理下载图片目录,严禁黑客通过此接口下载 users.json 或账本数据!
allowed_dirs = ["uploads/", "avatars/", "covers/"]
if not any(path.startswith(d) for d in allowed_dirs):
raise HTTPException(status_code=403, detail="非法访问:该接口仅允许代理图片资源")
media_extensions = {"jpg", "jpeg", "png", "gif", "webp", "mp4", "webm", "mov", "wav", "mp3", "m4a", "ogg"}
if path.rsplit(".", 1)[-1].lower() not in media_extensions:
raise HTTPException(status_code=403, detail="该接口不允许访问非媒体文件")
hf_token = os.environ.get("HF_TOKEN")
dataset_repo_id = store.DATASET_REPO_ID
try:
# hf_hub_download 会自动利用云端容器的缓存,只有第一次会去真实请求 Dataset
cached_file_path = download(
repo_id=dataset_repo_id,
repo_type="dataset",
filename=path,
token=hf_token
)
# 智能识别文件类型 (image/jpeg, image/png 等)
content_type, _ = mimetypes.guess_type(cached_file_path)
return file_response(cached_file_path, media_type=content_type or "application/octet-stream")
except Exception as e:
error_id = f"ERR_{int(time.time())}_{uuid.uuid4().hex[:8]}"
upstream_status = getattr(getattr(e, "response", None), "status_code", None)
if not isinstance(upstream_status, int):
upstream_status = getattr(e, "code", None)
status_text = f" status={upstream_status}" if isinstance(upstream_status, int) and 100 <= upstream_status <= 599 else ""
logger.warning(f"IMAGE_PROXY_FAIL | error_id={error_id} | error_type={type(e).__name__}{status_text}")
return JSONResponse(
status_code=502,
content=error_response(502, "图片暂时无法获取,请稍后重试", "upstream_error", error_id=error_id),
)