From 5c79a9aa00855abc65508f519bc34ee992cba574 Mon Sep 17 00:00:00 2001 From: LeonspaceX Date: Sun, 1 Feb 2026 13:24:10 +0800 Subject: [PATCH] Unify success codes and update upload deps --- TODO(记得提交到github前删!!!).txt | 2 ++ back/main.py | 45 +++++++++++++++++++++++----- back/requirements.txt | 1 + code_meaning.md | 11 ++++--- front/src/api.ts | 9 ++++-- front/src/components/CreatePost.tsx | 9 +++++- 6 files changed, 60 insertions(+), 17 deletions(-) diff --git a/TODO(记得提交到github前删!!!).txt b/TODO(记得提交到github前删!!!).txt index 459e2dc..5c154ac 100644 --- a/TODO(记得提交到github前删!!!).txt +++ b/TODO(记得提交到github前删!!!).txt @@ -10,3 +10,5 @@ rate limit功能 rss功能 + +完成开发后记得Debug=False diff --git a/back/main.py b/back/main.py index a3d9f2e..8086f69 100644 --- a/back/main.py +++ b/back/main.py @@ -8,6 +8,8 @@ import os import uuid import json import filetype +from PIL import Image +from PIL import UnidentifiedImageError from datetime import datetime app = Flask(__name__) @@ -212,6 +214,23 @@ def save_hashtags(tag_type, target_id, hashtopic): ) 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端点 --- @app.route('/api/settings', methods=['GET']) def get_settings(): @@ -244,7 +263,7 @@ def get_about(): "data": settings.about }) else: - # about在初始化时不会被设置,避免管理面板报错,返回默认文本 + # about在初始化时不会被设置,避免报错,返回默认文本 return jsonify({ "code": 1000, "data": "# 默认关于页面\n关于页面未设置,请前往管理面板操作。" @@ -354,7 +373,7 @@ def submit_post(): save_hashtags(0, new_post.id, hashtopic) 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}}) except Exception as e: db.session.rollback() @@ -409,7 +428,7 @@ def submit_comment(): save_hashtags(1, new_comment.id, hashtopic) 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: db.session.rollback() return jsonify({"code": 2003, "data": f"评论失败: {str(e)}"}) @@ -448,7 +467,7 @@ def submit_report(): db.session.add(report) db.session.commit() - return jsonify({"code": 1001, "data": {"id": report.id}}) + return jsonify({"code": 1000, "data": {"id": report.id}}) except Exception as e: return jsonify({"code": 2003, "data": f"投诉失败: {str(e)}"}) @@ -499,15 +518,27 @@ def upload_pic(): if FILE_SIZE_LIMIT_MB is not None: limit_bytes = float(FILE_SIZE_LIMIT_MB) * 1024 * 1024 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() kind = filetype.guess(file.read(5120)) file.seek(0) 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": "上传的文件类型不支持"}) + 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: ext = kind.extension 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.commit() - return jsonify({"code": 1001, "data": f"/api/files/{filename}"}) + return jsonify({"code": 1000, "data": f"/api/files/{filename}"}) except Exception as e: return jsonify({"code": 2003, "data": str(e)}) diff --git a/back/requirements.txt b/back/requirements.txt index 37d95ad..05b1702 100644 --- a/back/requirements.txt +++ b/back/requirements.txt @@ -2,3 +2,4 @@ Flask>=3.0.3 Flask-CORS>=4.0.1 Flask-SQLAlchemy>=3.1.1 filetype>=1.2.0 +Pillow>=10.0.0 diff --git a/code_meaning.md b/code_meaning.md index 76a302a..2743b9e 100644 --- a/code_meaning.md +++ b/code_meaning.md @@ -28,18 +28,17 @@ | Code | 含义 | | ---- | ---------------------------------------------------- | -| 1000 | 正常。适用于大多数成功的GET请求的返回。 | -| 1001 | 正常。适用于大多数成功的POST请求的返回。 | +| 1000 | 正常。适用于大多数成功的请求的返回。 | | 1002 | 正常。提交内容需要等待审核。 | -| 2000 | 失败。请求方式错误,例如缺少指定参数。 | +| 2000 | 失败。请求格式错误,例如缺少指定参数。 | | 2001 | 失败。未初始化。不应该在成功初始化后继续使用该code。 | | 2002 | 失败。数据不存在。 | -| 2003 | 失败。服务器内部错误。 | +| 2003 | 失败。服务器内部错误。表示未预期的服务端异常,不应频繁出现。 | | 2004 | 失败。试图使用不存在的Identity。 | | 2005 | 失败。提交内容包含违禁词。 | | 2006 | 失败。上传的图片超出限制大小。 | -| 2007 | 失败。上传的文件类型不支持。 | -| 404 | api端点不存在。 | +| 2007 | 失败。上传的图片类型不支持。 | +| 2008 | 失败。上传的图片损坏。 | | | | | | | | | | diff --git a/front/src/api.ts b/front/src/api.ts index d3c7bdc..1b14314 100644 --- a/front/src/api.ts +++ b/front/src/api.ts @@ -431,7 +431,7 @@ export const postComment = async (commentData: PostCommentRequest): Promise => { } const json = await response.json(); handlePostApiCode(json); - if (json.code === 1001 && typeof json.data === 'string') { + if (json.code === 1000 && typeof json.data === 'string') { return json.data; } if (json.code === 2006) { throw new Error('UPLOAD_TOO_LARGE'); } + if (json.code === 2008) { + throw new Error('CORRUPTED_IMAGE'); + } if (json.code === 2007) { throw new Error('UNSUPPORTED_FORMAT'); } diff --git a/front/src/components/CreatePost.tsx b/front/src/components/CreatePost.tsx index 976be93..c1eb64d 100644 --- a/front/src/components/CreatePost.tsx +++ b/front/src/components/CreatePost.tsx @@ -214,7 +214,7 @@ const CreatePost: React.FC = () => { try { const response = await createPost(value); - if (response.code === 1001 || response.code === 1002) { + if (response.code === 1000 || response.code === 1002) { // 清除草稿 saveDraft(''); setValue(''); @@ -318,6 +318,13 @@ const CreatePost: React.FC = () => { , { intent: 'error' } ); + } else if (msg.includes('CORRUPTED_IMAGE')) { + dispatchToast( + + 上传的文件损坏 + , + { intent: 'error' } + ); } else if (msg.includes('UNSUPPORTED_FORMAT')) { dispatchToast(