Unify success codes and update upload deps

This commit is contained in:
LeonspaceX
2026-02-01 13:24:10 +08:00
parent 3e2cdf4c74
commit 5c79a9aa00
6 changed files with 60 additions and 17 deletions

View File

@@ -10,3 +10,5 @@
rate limit功能 rate limit功能
rss功能 rss功能
完成开发后记得Debug=False

View File

@@ -8,6 +8,8 @@ import os
import uuid import uuid
import json import json
import filetype import filetype
from PIL import Image
from PIL import UnidentifiedImageError
from datetime import datetime from datetime import datetime
app = Flask(__name__) app = Flask(__name__)
@@ -212,6 +214,23 @@ def save_hashtags(tag_type, target_id, hashtopic):
) )
db.session.add(new_tag) db.session.add(new_tag)
def mime_allowed(mime, rules):
if not rules:
return True
if not mime:
return False
mime = mime.lower()
for rule in rules:
rule = str(rule).strip().lower()
if not rule:
continue
if rule == 'image/*':
if mime.startswith('image/'):
return True
if mime == rule:
return True
return False
# --- 用户普通api端点 --- # --- 用户普通api端点 ---
@app.route('/api/settings', methods=['GET']) @app.route('/api/settings', methods=['GET'])
def get_settings(): def get_settings():
@@ -244,7 +263,7 @@ def get_about():
"data": settings.about "data": settings.about
}) })
else: else:
# about在初始化时不会被设置避免管理面板报错,返回默认文本 # about在初始化时不会被设置避免报错返回默认文本
return jsonify({ return jsonify({
"code": 1000, "code": 1000,
"data": "# 默认关于页面\n关于页面未设置,请前往管理面板操作。" "data": "# 默认关于页面\n关于页面未设置,请前往管理面板操作。"
@@ -354,7 +373,7 @@ def submit_post():
save_hashtags(0, new_post.id, hashtopic) save_hashtags(0, new_post.id, hashtopic)
db.session.commit() db.session.commit()
code = 1002 if new_post.status == 'Pending' else 1001 code = 1002 if new_post.status == 'Pending' else 1000
return jsonify({"code": code, "data": {"id": new_post.id}}) return jsonify({"code": code, "data": {"id": new_post.id}})
except Exception as e: except Exception as e:
db.session.rollback() db.session.rollback()
@@ -409,7 +428,7 @@ def submit_comment():
save_hashtags(1, new_comment.id, hashtopic) save_hashtags(1, new_comment.id, hashtopic)
db.session.commit() db.session.commit()
return jsonify({"code": 1001, "data": {"id": new_comment.id}}) return jsonify({"code": 1000, "data": {"id": new_comment.id}})
except Exception as e: except Exception as e:
db.session.rollback() db.session.rollback()
return jsonify({"code": 2003, "data": f"评论失败: {str(e)}"}) return jsonify({"code": 2003, "data": f"评论失败: {str(e)}"})
@@ -448,7 +467,7 @@ def submit_report():
db.session.add(report) db.session.add(report)
db.session.commit() db.session.commit()
return jsonify({"code": 1001, "data": {"id": report.id}}) return jsonify({"code": 1000, "data": {"id": report.id}})
except Exception as e: except Exception as e:
return jsonify({"code": 2003, "data": f"投诉失败: {str(e)}"}) return jsonify({"code": 2003, "data": f"投诉失败: {str(e)}"})
@@ -499,15 +518,27 @@ def upload_pic():
if FILE_SIZE_LIMIT_MB is not None: if FILE_SIZE_LIMIT_MB is not None:
limit_bytes = float(FILE_SIZE_LIMIT_MB) * 1024 * 1024 limit_bytes = float(FILE_SIZE_LIMIT_MB) * 1024 * 1024
if file_length > limit_bytes: if file_length > limit_bytes:
return jsonify({"code": 2006, "data": "上传的图片超出限制大小"}) return jsonify({"code": 2006, "data": f"上传的图片超出{FILE_SIZE_LIMIT_MB}MB限制大小"})
ext = os.path.splitext(file.filename)[1].lstrip('.').lower() ext = os.path.splitext(file.filename)[1].lstrip('.').lower()
kind = filetype.guess(file.read(5120)) kind = filetype.guess(file.read(5120))
file.seek(0) file.seek(0)
detected_mime = kind.mime if kind else None detected_mime = kind.mime if kind else None
if not detected_mime or (FILE_FORMATS and detected_mime.lower() not in FILE_FORMATS): if not detected_mime or not mime_allowed(detected_mime, FILE_FORMATS):
return jsonify({"code": 2007, "data": "上传的文件类型不支持"}) return jsonify({"code": 2007, "data": "上传的文件类型不支持"})
try:
file.seek(0)
img = Image.open(file)
img.verify()
file.seek(0)
except (UnidentifiedImageError, OSError):
file.seek(0)
return jsonify({"code": 2008, "data": "上传的文件损坏"})
except Exception:
file.seek(0)
return jsonify({"code": 2008, "data": "上传的文件损坏"})
if not ext and kind: if not ext and kind:
ext = kind.extension ext = kind.extension
filename = f"{uuid.uuid4().hex}.{ext}" if ext else uuid.uuid4().hex filename = f"{uuid.uuid4().hex}.{ext}" if ext else uuid.uuid4().hex
@@ -519,7 +550,7 @@ def upload_pic():
db.session.add(ImgFile(path=filename, name=name, identity_token=identity_token)) db.session.add(ImgFile(path=filename, name=name, identity_token=identity_token))
db.session.commit() db.session.commit()
return jsonify({"code": 1001, "data": f"/api/files/{filename}"}) return jsonify({"code": 1000, "data": f"/api/files/{filename}"})
except Exception as e: except Exception as e:
return jsonify({"code": 2003, "data": str(e)}) return jsonify({"code": 2003, "data": str(e)})

View File

@@ -2,3 +2,4 @@ Flask>=3.0.3
Flask-CORS>=4.0.1 Flask-CORS>=4.0.1
Flask-SQLAlchemy>=3.1.1 Flask-SQLAlchemy>=3.1.1
filetype>=1.2.0 filetype>=1.2.0
Pillow>=10.0.0

View File

@@ -28,18 +28,17 @@
| Code | 含义 | | Code | 含义 |
| ---- | ---------------------------------------------------- | | ---- | ---------------------------------------------------- |
| 1000 | 正常。适用于大多数成功的GET请求的返回。 | | 1000 | 正常。适用于大多数成功的请求的返回。 |
| 1001 | 正常。适用于大多数成功的POST请求的返回。 |
| 1002 | 正常。提交内容需要等待审核。 | | 1002 | 正常。提交内容需要等待审核。 |
| 2000 | 失败。请求式错误,例如缺少指定参数。 | | 2000 | 失败。请求式错误,例如缺少指定参数。 |
| 2001 | 失败。未初始化。不应该在成功初始化后继续使用该code。 | | 2001 | 失败。未初始化。不应该在成功初始化后继续使用该code。 |
| 2002 | 失败。数据不存在。 | | 2002 | 失败。数据不存在。 |
| 2003 | 失败。服务器内部错误。 | | 2003 | 失败。服务器内部错误。表示未预期的服务端异常,不应频繁出现。 |
| 2004 | 失败。试图使用不存在的Identity。 | | 2004 | 失败。试图使用不存在的Identity。 |
| 2005 | 失败。提交内容包含违禁词。 | | 2005 | 失败。提交内容包含违禁词。 |
| 2006 | 失败。上传的图片超出限制大小。 | | 2006 | 失败。上传的图片超出限制大小。 |
| 2007 | 失败。上传的文件类型不支持。 | | 2007 | 失败。上传的图片类型不支持。 |
| 404 | api端点不存在。 | | 2008 | 失败。上传的图片损坏。 |
| | | | | |
| | | | | |
| | | | | |

View File

@@ -431,7 +431,7 @@ export const postComment = async (commentData: PostCommentRequest): Promise<Post
const json = await response.json(); const json = await response.json();
handlePostApiCode(json); handlePostApiCode(json);
if (json.code === 1001 && json.data?.id !== undefined) { if (json.code === 1000 && json.data?.id !== undefined) {
return { id: Number(json.data.id) }; return { id: Number(json.data.id) };
} }
if (json.code === 2005) { if (json.code === 2005) {
@@ -466,7 +466,7 @@ export const reportPost = async (reportData: { id: number; title: string; conten
} }
const json = await response.json(); const json = await response.json();
handlePostApiCode(json); handlePostApiCode(json);
if (json.code === 1001 && json.data?.id !== undefined) { if (json.code === 1000 && json.data?.id !== undefined) {
return { id: Number(json.data.id) }; return { id: Number(json.data.id) };
} }
throw new Error(json.data || 'Report failed'); throw new Error(json.data || 'Report failed');
@@ -493,12 +493,15 @@ export const uploadImage = async (file: File): Promise<string> => {
} }
const json = await response.json(); const json = await response.json();
handlePostApiCode(json); handlePostApiCode(json);
if (json.code === 1001 && typeof json.data === 'string') { if (json.code === 1000 && typeof json.data === 'string') {
return json.data; return json.data;
} }
if (json.code === 2006) { if (json.code === 2006) {
throw new Error('UPLOAD_TOO_LARGE'); throw new Error('UPLOAD_TOO_LARGE');
} }
if (json.code === 2008) {
throw new Error('CORRUPTED_IMAGE');
}
if (json.code === 2007) { if (json.code === 2007) {
throw new Error('UNSUPPORTED_FORMAT'); throw new Error('UNSUPPORTED_FORMAT');
} }

View File

@@ -214,7 +214,7 @@ const CreatePost: React.FC = () => {
try { try {
const response = await createPost(value); const response = await createPost(value);
if (response.code === 1001 || response.code === 1002) { if (response.code === 1000 || response.code === 1002) {
// 清除草稿 // 清除草稿
saveDraft(''); saveDraft('');
setValue(''); setValue('');
@@ -318,6 +318,13 @@ const CreatePost: React.FC = () => {
</Toast>, </Toast>,
{ intent: 'error' } { intent: 'error' }
); );
} else if (msg.includes('CORRUPTED_IMAGE')) {
dispatchToast(
<Toast>
<ToastTitle></ToastTitle>
</Toast>,
{ intent: 'error' }
);
} else if (msg.includes('UNSUPPORTED_FORMAT')) { } else if (msg.includes('UNSUPPORTED_FORMAT')) {
dispatchToast( dispatchToast(
<Toast> <Toast>