ZHIWEI666 commited on
Commit
16c304a
·
verified ·
1 Parent(s): 58595a3

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +52 -13
app.py CHANGED
@@ -1,7 +1,7 @@
1
  # ⚙️ 后端逻辑/核心服务端.py (Hugging Face Spaces app.py)
2
  from fastapi import FastAPI, File, UploadFile, Form, Depends, HTTPException
3
  from fastapi.middleware.cors import CORSMiddleware
4
- from fastapi.responses import Response, JSONResponse
5
  from sqlalchemy.orm import Session
6
  from pydantic import BaseModel
7
  from huggingface_hub import hf_hub_download, HfApi
@@ -10,6 +10,7 @@ import urllib.parse
10
  import urllib.request
11
  import urllib.error
12
  import os
 
13
  import 数据库连接 as db
14
 
15
  from router_users import router as users_router
@@ -24,9 +25,6 @@ from models_sql import Ownership
24
 
25
  app = FastAPI(title="ComfyUI Ranking Community API")
26
 
27
- # ==========================================
28
- # 增加一个根目录健康检查接口,专治 HF Spaces 的 "Restarting" 误判
29
- # ==========================================
30
  @app.get("/")
31
  def health_check():
32
  return {"status": "ok", "message": "ComfyUI Ranking API is running perfectly!"}
@@ -36,7 +34,6 @@ def on_startup():
36
  init_sql_db()
37
  print("关系型数据库加载完毕,金融表同步完成。")
38
 
39
- # 🟢 致命 BUG 修复:allow_credentials 必须为 False 才能配合 origins=["*"]
40
  app.add_middleware(
41
  CORSMiddleware,
42
  allow_origins=["*"],
@@ -52,18 +49,60 @@ app.include_router(messages_router)
52
  app.include_router(wallet_router)
53
  app.include_router(proxy_router)
54
 
55
- # 🟢 性能隐患修复:去掉 async def,改为 def。让 FastAPI 自动分配底层线程,防止上传大文件时全站卡死!
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
  @app.post("/api/upload")
57
  def upload_file(file: UploadFile = File(...), file_type: str = Form(...)):
58
- # 同步读取文件内容
59
  content = file.file.read()
60
 
61
- # 🟢 动态文件大小风控
62
- max_size = 10 * 1024 * 1024 # 默认兜底 10MB
63
  if file_type == "avatar":
64
- max_size = 2 * 1024 * 1024 # 头像严格限制为 2MB
65
  elif file_type == "cover":
66
- max_size = 5 * 1024 * 1024 # 封面图限制为 5MB
67
 
68
  if len(content) > max_size:
69
  raise HTTPException(status_code=400, detail=f"文件过大,{file_type} 类型请限制在 {max_size // (1024*1024)}MB 以内")
@@ -98,7 +137,8 @@ def upload_file(file: UploadFile = File(...), file_type: str = Form(...)):
98
  if os.path.exists(local_tmp_path):
99
  os.remove(local_tmp_path)
100
 
101
- permanent_url = f"https://huggingface.co/datasets/{dataset_repo_id}/resolve/main/uploads/{file_type}/{safe_filename}"
 
102
  return {"status": "success", "url": permanent_url}
103
 
104
 
@@ -107,7 +147,6 @@ class ValidateResourceRequest(BaseModel):
107
  item_id: str
108
  account: str
109
 
110
- # 🟢 性能隐患修复:去掉 async def,防止 urllib.request 阻塞事件循环
111
  @app.post("/api/validate_resource")
112
  def validate_resource(req_data: ValidateResourceRequest, sql_db: Session = Depends(get_db)):
113
  target_url = req_data.url
 
1
  # ⚙️ 后端逻辑/核心服务端.py (Hugging Face Spaces app.py)
2
  from fastapi import FastAPI, File, UploadFile, Form, Depends, HTTPException
3
  from fastapi.middleware.cors import CORSMiddleware
4
+ from fastapi.responses import Response, JSONResponse, FileResponse # 🟢 新增 FileResponse
5
  from sqlalchemy.orm import Session
6
  from pydantic import BaseModel
7
  from huggingface_hub import hf_hub_download, HfApi
 
10
  import urllib.request
11
  import urllib.error
12
  import os
13
+ import mimetypes # 🟢 新增,用于识别图片类型
14
  import 数据库连接 as db
15
 
16
  from router_users import router as users_router
 
25
 
26
  app = FastAPI(title="ComfyUI Ranking Community API")
27
 
 
 
 
28
  @app.get("/")
29
  def health_check():
30
  return {"status": "ok", "message": "ComfyUI Ranking API is running perfectly!"}
 
34
  init_sql_db()
35
  print("关系型数据库加载完毕,金融表同步完成。")
36
 
 
37
  app.add_middleware(
38
  CORSMiddleware,
39
  allow_origins=["*"],
 
49
  app.include_router(wallet_router)
50
  app.include_router(proxy_router)
51
 
52
+ # ==========================================
53
+ # 🟢 新增:私有图床代理中心 (Image Proxy)
54
+ # 解决 Private 仓库下,本地客户端报 401 Unauthorized 的终极方案
55
+ # ==========================================
56
+ @app.get("/api/image_proxy")
57
+ def proxy_hf_image(url: str = None, path: str = None):
58
+ """云端图片代理:使用云端的 HF_TOKEN 提取私有图床图片并返回给没有任何权限的本地端"""
59
+
60
+ # 兼容处理:如果本地发来的是已经被污染的老版本 HF 直链,我们自动将其转换为相对路径
61
+ if url and url.startswith("https://huggingface.co/datasets/"):
62
+ try:
63
+ path = url.split("resolve/main/")[-1]
64
+ path = urllib.parse.unquote(path)
65
+ except:
66
+ raise HTTPException(status_code=400, detail="无效的 HF 原链接格式")
67
+
68
+ if not path:
69
+ raise HTTPException(status_code=400, detail="缺少路径参数")
70
+
71
+ # 🛡️ 绝对的安全红线:限制只能代理下载图片目录,严禁黑客通过此接口下载 users.json 或账本数据!
72
+ allowed_dirs = ["uploads/", "avatars/", "covers/"]
73
+ if not any(path.startswith(d) for d in allowed_dirs):
74
+ raise HTTPException(status_code=403, detail="非法访问:该接口仅允许代理图片资源")
75
+
76
+ hf_token = os.environ.get("HF_TOKEN")
77
+ dataset_repo_id = db.DATASET_REPO_ID
78
+
79
+ try:
80
+ # hf_hub_download 会自动利用云端容器的缓存,只有第一次会去真实请求 Dataset
81
+ cached_file_path = hf_hub_download(
82
+ repo_id=dataset_repo_id,
83
+ repo_type="dataset",
84
+ filename=path,
85
+ token=hf_token
86
+ )
87
+ # 智能识别文件类型 (image/jpeg, image/png 等)
88
+ content_type, _ = mimetypes.guess_type(cached_file_path)
89
+ return FileResponse(cached_file_path, media_type=content_type or "application/octet-stream")
90
+ except Exception as e:
91
+ return JSONResponse(content={"error": f"代理获取图片失败: {str(e)}"}, status_code=404)
92
+
93
+ # ==========================================
94
+ # 上传接口 (将返回的 URL 替换为 Proxy 代理链接)
95
+ # ==========================================
96
  @app.post("/api/upload")
97
  def upload_file(file: UploadFile = File(...), file_type: str = Form(...)):
 
98
  content = file.file.read()
99
 
100
+ # 动态文件大小风控
101
+ max_size = 10 * 1024 * 1024
102
  if file_type == "avatar":
103
+ max_size = 2 * 1024 * 1024
104
  elif file_type == "cover":
105
+ max_size = 5 * 1024 * 1024
106
 
107
  if len(content) > max_size:
108
  raise HTTPException(status_code=400, detail=f"文件过大,{file_type} 类型请限制在 {max_size // (1024*1024)}MB 以内")
 
137
  if os.path.exists(local_tmp_path):
138
  os.remove(local_tmp_path)
139
 
140
+ # 🚀 核心修复:不再返回暴露隐私且报 401 的 HF 直链,而是返回我们刚写好的 Proxy 代理链接
141
+ permanent_url = f"https://zhiwei666-comfyui-ranking-api.hf.space/api/image_proxy?path=uploads/{file_type}/{safe_filename}"
142
  return {"status": "success", "url": permanent_url}
143
 
144
 
 
147
  item_id: str
148
  account: str
149
 
 
150
  @app.post("/api/validate_resource")
151
  def validate_resource(req_data: ValidateResourceRequest, sql_db: Session = Depends(get_db)):
152
  target_url = req_data.url