chb2026 commited on
Commit
31c4369
·
verified ·
1 Parent(s): 2b45657

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +125 -0
app.py ADDED
@@ -0,0 +1,125 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import base64
3
+ import hashlib
4
+ import mimetypes
5
+ from datetime import datetime
6
+ from io import BytesIO
7
+
8
+ from flask import Flask, request, jsonify, redirect
9
+ from huggingface_hub import HfApi, HfFileSystem
10
+ from PIL import Image
11
+ import uuid
12
+
13
+ app = Flask(__name__)
14
+
15
+ # 环境变量配置
16
+ HF_TOKEN = os.environ.get("HF_TOKEN")
17
+ DATASET_ID = os.environ.get("DATASET_ID")
18
+ MAX_SIZE = int(os.environ.get("MAX_SIZE", 10)) * 1024 * 1024 # 转字节
19
+ API_KEY = os.environ.get("API_KEY")
20
+
21
+ fs = HfFileSystem(token=HF_TOKEN)
22
+ hf_api = HfApi(token=HF_TOKEN)
23
+
24
+ def validate_auth():
25
+ if not API_KEY:
26
+ return True
27
+ header_key = request.headers.get("X-API-Key")
28
+ param_key = request.args.get("key")
29
+ return header_key == API_KEY or param_key == API_KEY
30
+
31
+ def generate_filename(data, mime_type=None):
32
+ ext = mimetypes.guess_extension(mime_type or "application/octet-stream") or ".bin"
33
+ unique_id = uuid.uuid4().hex[:8]
34
+ timestamp = datetime.now().strftime("%Y%m%d%H%M%S")
35
+ return f"{timestamp}-{unique_id}{ext}"
36
+
37
+ def save_to_dataset(content, filename):
38
+ path = f"datasets/{DATASET_ID}/resolve/main/images/{filename}"
39
+ fs.mkdir(f"datasets/{DATASET_ID}/images", exist_ok=True)
40
+ fs.write_bytes(f"datasets/{DATASET_ID}/images/{filename}", content)
41
+ return f"https://huggingface.co/datasets/{DATASET_ID}/resolve/main/images/{filename}"
42
+
43
+ @app.route("/", methods=["GET"])
44
+ def index():
45
+ return "PICGO is running..."
46
+
47
+ @app.route("/api/1/upload", methods=["GET", "POST"])
48
+ def upload():
49
+ # 鉴权检查
50
+ if not validate_auth():
51
+ return jsonify({
52
+ "status_code": 401,
53
+ "error": {"message": "Invalid API key"},
54
+ "status_txt": "Unauthorized"
55
+ }), 401
56
+
57
+ # 获取文件数据
58
+ source = None
59
+ if request.method == "POST":
60
+ if "source" in request.files:
61
+ file = request.files["source"]
62
+ source = file.read()
63
+ else:
64
+ source = request.form.get("source")
65
+ else:
66
+ source = request.args.get("source")
67
+
68
+ # 处理Base64、文件或URL
69
+ if isinstance(source, bytes):
70
+ content = source
71
+ elif source.startswith(("http://", "https://")):
72
+ # 需要实现URL下载逻辑(示例代码省略)
73
+ return jsonify({"error": "URL download not implemented"}), 501
74
+ elif source.startswith("data:"):
75
+ header, data = source.split(",", 1)
76
+ mime_type = header.split(":")[1].split(";")[0]
77
+ content = base64.b64decode(data)
78
+ else:
79
+ content = base64.b64decode(source)
80
+
81
+ # 验证大小限制
82
+ if len(content) > MAX_SIZE:
83
+ return jsonify({
84
+ "status_code": 413,
85
+ "error": {"message": f"File exceeds {MAX_SIZE//1024//1024}MB limit"},
86
+ "status_txt": "Payload Too Large"
87
+ }), 413
88
+
89
+ # 处理图片属性
90
+ try:
91
+ image = Image.open(BytesIO(content))
92
+ width, height = image.size
93
+ mime_type = image.get_format_mimetype()
94
+ except:
95
+ width = height = 0
96
+ mime_type = None
97
+
98
+ # 生成存储信息
99
+ filename = generate_filename(content, mime_type)
100
+ file_url = save_to_dataset(content, filename)
101
+
102
+ # 构造响应
103
+ response_format = request.args.get("format", "json")
104
+ if response_format == "txt":
105
+ return file_url
106
+ elif response_format == "redirect":
107
+ return redirect(file_url, code=302)
108
+ else:
109
+ return jsonify({
110
+ "status_code": 200,
111
+ "success": {"message": "file uploaded", "code": 200},
112
+ "image": {
113
+ "filename": filename,
114
+ "url": file_url,
115
+ "size": len(content),
116
+ "width": width,
117
+ "height": height,
118
+ "mime": mime_type,
119
+ "size_formatted": f"{len(content)/1024/1024:.1f} MB"
120
+ },
121
+ "status_txt": "OK"
122
+ })
123
+
124
+ if __name__ == "__main__":
125
+ app.run(host="0.0.0.0", port=7860)