You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用HTTP POST向Python Flask服务器上传文件时文件名特殊字符丢失

解决FormData上传含特殊字符文件名的丢失问题

我来帮你搞定这个问题!你上传的2^8.txt到Flask后端后变成了28.txt,核心问题出在Flask的secure_filename函数上,还有你之前用encodeURI()找错了方向——因为FormData里的文件名不是URL参数,所以这个编码方法根本不起作用。

问题根源

secure_filename是Werkzeug(Flask依赖的工具库)提供的安全处理函数,它会过滤掉所有它认为"不安全"的字符,其中就包括^这类符号。它的设计目的是防止恶意文件名(比如包含路径遍历的../)带来的安全风险,但同时也会误杀一些你需要的特殊字符。

三种解决方案

方案一:直接使用原始文件名(简单但需注意安全)

如果你的业务场景可以接受直接使用用户上传的原始文件名,完全可以跳过secure_filename的处理:

if request.method == 'POST':
    if 'file' not in request.files:
        flash('No file part')
        return jsonify(status="fail")
    file = request.files['file']
    # 直接取原始文件名,不做过滤
    filename = file.filename
    print(filename)  # 现在会正确输出2^8.txt

⚠️ 注意:这种方式要警惕安全风险,比如用户上传../../malware.exe这类文件名,可能会导致文件被存到不该存的位置,建议额外加一层路径校验。

方案二:自定义安全文件名过滤规则

如果需要保留^这类字符,同时过滤真正危险的路径字符,可以自己实现一个过滤函数,替代secure_filename:

import re
from flask import request, flash, jsonify

def custom_secure_filename(filename):
    # 只过滤掉路径相关的危险字符(比如/、\、..等),保留^、_、-、.等安全符号
    # 把所有不符合规则的字符替换成下划线
    return re.sub(r'[^\w\-\.^]', '_', filename)

if request.method == 'POST':
    if 'file' not in request.files:
        flash('No file part')
        return jsonify(status="fail")
    file = request.files['file']
    filename = custom_secure_filename(file.filename)
    print(filename)  # 输出2^8.txt

这个函数只移除那些可能导致路径遍历的危险字符,同时保留你需要的^符号,兼顾安全和需求。

方案三:前端编码+后端解码

如果不想改动后端的secure_filename逻辑,也可以在前端对文件名进行URL编码,后端再解码还原:

  • 前端代码修改:
var fileSelect = document.getElementById('myfile');
var files = fileSelect.files;
var formData = new FormData();
var file = files[0];
// 用encodeURIComponent编码文件名,而不是encodeURI
var encodedFilename = encodeURIComponent(file.name);
formData.append('file', file, encodedFilename);
  • 后端代码修改:
from urllib.parse import unquote
from flask import request, flash, jsonify

if request.method == 'POST':
    if 'file' not in request.files:
        flash('No file part')
        return jsonify(status="fail")
    file = request.files['file']
    # 先解码文件名,再按需处理
    filename = unquote(file.filename)
    print(filename)  # 输出2^8.txt

这里要注意用encodeURIComponent而不是encodeURI,前者会编码所有特殊字符(包括^),后端用unquote就能完美还原。

总结

最推荐的是方案二,既能保留你需要的特殊字符,又能保证基本的安全。如果追求简单,方案一也可以,但一定要做好安全校验。

内容的提问来源于stack exchange,提问作者zifan yan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 11:17:36