Spaces:
Running
Running
| # ⚙️ 后端逻辑/核心服务端.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) | |
| def read_root(): | |
| return {"status": "ok", "message": "API is running and fully modularized!"} | |
| 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 | |
| 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) |