修复中文文件名上传wav误判为不支持类型

1. 上传扩展名校验改为基于原始文件名提取,避免secure_filename清洗后丢失点号导致误判。

2. 重建安全文件名时分离basename和扩展名,兼容中文文件名与无效basename场景。

3. 继续保留媒体类型白名单校验,不放宽安全边界。
This commit is contained in:
liuwei
2026-04-23 13:50:02 +08:00
parent df6f9f4cfa
commit 37d6c36e2c

View File

@@ -81,12 +81,11 @@ def _validate_payload(payload: Dict[str, Any], service) -> str:
return ""
def _allowed_file(filename: str, media_type: str) -> bool:
"""判断上传文件扩展名是否允许"""
if "." not in filename:
return False
ext = filename.rsplit(".", 1)[1].lower()
return ext in ALLOWED_EXTENSIONS.get(media_type, set())
def _extract_file_ext(filename: str) -> str:
"""从原始文件名提取扩展名(小写,不含点)"""
if "." not in str(filename or ""):
return ""
return str(filename).rsplit(".", 1)[1].lower().strip()
@fun_command_rules_bp.route("/")
@@ -115,9 +114,19 @@ def api_upload_media():
if not upload_file or not upload_file.filename:
return jsonify({"success": False, "message": "文件名为空"}), 400
filename = secure_filename(upload_file.filename)
if not _allowed_file(filename, media_type):
return jsonify({"success": False, "message": f"不支持的文件类型: {filename}"}), 400
# 注意secure_filename 对中文文件名会清洗成 “wav” 这类无点字符串,
# 若直接基于清洗后文件名做扩展名校验会误判。这里改为优先使用原始文件名提取扩展名。
raw_filename = str(upload_file.filename or "").strip()
file_ext = _extract_file_ext(raw_filename)
if file_ext not in ALLOWED_EXTENSIONS.get(media_type, set()):
return jsonify({"success": False, "message": f"不支持的文件类型: {raw_filename}"}), 400
# 生成安全文件名basename 走 secure_filename扩展名使用原始提取值兜底。
raw_basename = raw_filename.rsplit(".", 1)[0] if "." in raw_filename else raw_filename
safe_basename = secure_filename(raw_basename).strip()
if not safe_basename:
safe_basename = "upload_file"
filename = f"{safe_basename}.{file_ext}"
# 按媒体类型分目录,便于后续清理和排查。
upload_root = os.path.join(current_app.root_path, "static", "uploads", "fun_command_rules", media_type)