fix(imagine): 自动纠正base64图片MIME避免上传403

This commit is contained in:
root authored and XianYuDaXian committed 2026-02-27 21:55:25 +08:00
1 parent e8f3e25135
commit 93f025aaab
1 file changed
+40 -3
+40 -3
View File
@@ -1,4 +1,6 @@
import asyncio
import base64
import binascii
import contextlib
import re
import time
@@ -135,18 +137,53 @@ def _extract_parent_post_id_from_payload(payload: Dict[str, Any]) -> str:
return ""
def _detect_image_mime_from_b64(compact_b64: str) -> str:
"""根据 base64 内容头判断真实图片 MIME。"""
try:
raw = base64.b64decode(compact_b64, validate=True)
except (binascii.Error, ValueError):
raise HTTPException(status_code=400, detail="image_base64 format is invalid")
if raw.startswith(b"\xff\xd8\xff"):
return "image/jpeg"
if raw.startswith(b"\x89PNG\r\n\x1a\n"):
return "image/png"
if raw.startswith(b"RIFF") and len(raw) >= 12 and raw[8:12] == b"WEBP":
return "image/webp"
if raw.startswith((b"GIF87a", b"GIF89a")):
return "image/gif"
# 无法识别时维持 png 兼容行为
return "image/png"
def _normalize_image_input(image_base64: str, image_url: str) -> str:
raw_b64 = str(image_base64 or "").strip()
raw_url = str(image_url or "").strip()
if raw_b64:
declared_mime = ""
compact = raw_b64
if raw_b64.startswith("data:"):
return raw_b64
compact = re.sub(r"\s+", "", raw_b64)
try:
header, payload = raw_b64.split(",", 1)
except ValueError:
raise HTTPException(status_code=400, detail="image_base64 format is invalid")
compact = payload
mime_part = header[5:].split(";", 1)[0].strip().lower()
declared_mime = mime_part
compact = re.sub(r"\s+", "", compact)
if not compact:
raise HTTPException(status_code=400, detail="image_base64 is empty")
if not re.fullmatch(r"[A-Za-z0-9+/=_-]+", compact):
raise HTTPException(status_code=400, detail="image_base64 format is invalid")
return f"data:image/png;base64,{compact}"
real_mime = _detect_image_mime_from_b64(compact)
if declared_mime and declared_mime != real_mime:
logger.warning(
"Imagine workbench image MIME mismatch corrected: "
f"declared={declared_mime}, detected={real_mime}"
)
return f"data:{real_mime};base64,{compact}"
if raw_url:
if raw_url.startswith("http://") or raw_url.startswith("https://"):
return raw_url