Spaces:
Running
Running
File size: 3,967 Bytes
c00dff0 d5dffcf be75899 94c35d7 da1038d 22d80b0 94c35d7 be75899 088dffd d5dffcf be75899 088dffd d5dffcf be75899 d5dffcf be75899 da1038d 90d7999 d5dffcf 90d7999 cfb2ea0 da1038d 90d7999 22d80b0 94c35d7 22d80b0 c3d648d 22d80b0 c3d648d 94c35d7 22d80b0 94c35d7 22d80b0 c3d648d 22d80b0 c3d648d 22d80b0 c3d648d 22d80b0 c3d648d | 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 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | # ⚙️ 后端逻辑/核心服务端.py (Hugging Face Spaces app.py)
from fastapi import FastAPI, File, UploadFile, Form
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import Response, JSONResponse
from pydantic import BaseModel # 【新增】:引入标准数据模型
import hashlib
import urllib.parse
import urllib.request
import os
import 数据库连接 as db
# 引入拆分后的四大业务模块
from router_users import router as users_router
from router_items import router as items_router
from router_comments import router as comments_router
from router_messages import router as messages_router
app = FastAPI(title="ComfyUI Ranking Community API")
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
app.include_router(users_router)
app.include_router(items_router)
app.include_router(comments_router)
app.include_router(messages_router)
@app.get("/")
def read_root():
return {"status": "ok", "message": "API is running and fully modularized!"}
@app.post("/api/upload")
async def upload_file(file: UploadFile = File(...), file_type: str = Form(...)):
content = await file.read()
file_hash = hashlib.md5(content).hexdigest()[:10]
new_filename = f"{file_hash}_{file.filename}"
safe_filename = urllib.parse.quote(file.filename)
safe_url_filename = f"{file_hash}_{safe_filename}"
dir_mapping = {"avatar": "avatars", "cover": "covers", "tool": "tools", "app": "apps"}
target_dir = dir_mapping.get(file_type, "others")
full_path_in_repo = f"{target_dir}/{new_filename}"
db.save_file(full_path_in_repo, content)
url = f"https://huggingface.co/datasets/{db.DATASET_REPO_ID}/resolve/main/{target_dir}/{safe_url_filename}"
return {"status": "success", "url": url, "display_name": file.filename, "hashed_name": new_filename}
# =========================================================
# 【核心修复】:使用 huggingface_hub 官方库替代 urllib 解决重定向 401 问题
# =========================================================
from huggingface_hub import hf_hub_download
class ProxyDownloadRequest(BaseModel):
url: str
@app.post("/api/proxy_download")
async def proxy_download(req_data: ProxyDownloadRequest):
target_url = req_data.url
# 校验 URL 格式
if not target_url or "resolve/main/" not in target_url:
return JSONResponse(content={"error": "无效的 Hugging Face 下载链接"}, status_code=400)
hf_token = os.environ.get("HF_TOKEN")
if not hf_token:
return JSONResponse(content={"error": "云端环境变量未配置 HF_TOKEN,无法读取私有库"}, status_code=401)
try:
# 1. 从前端传来的 URL 中切割出仓库内的真实相对路径
# 例如从 https://.../resolve/main/apps/123_%E6%B5%8B.json 提取出 apps/123_%E6%B5%8B.json
repo_path_encoded = target_url.split("resolve/main/")[-1]
# 2. 对可能存在的被编码的中文字符进行解码 (恢复为 apps/123_测.json)
repo_path = urllib.parse.unquote(repo_path_encoded)
# 3. 调用官方库直接从私有 Dataset 拉取文件(完美处理鉴权和重定向)
cached_file_path = hf_hub_download(
repo_id=db.DATASET_REPO_ID,
repo_type="dataset",
filename=repo_path,
token=hf_token
)
# 4. 读取缓存在云端的本地文件流并返回给前端
with open(cached_file_path, "rb") as f:
content = f.read()
return Response(content=content, media_type="application/json")
except Exception as e:
return JSONResponse(content={"error": f"云端官方库读取失败: {str(e)}"}, status_code=500) |