ZHIWEI666's picture
Upload app.py
c3d648d verified
raw
history blame
3.97 kB
# ⚙️ 后端逻辑/核心服务端.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)