Flask上传超限返回413错误,需在app = Flask(__name__)后立即设置app.config['MAX_CONTENT_LENGTH'](单位字节),并同步调整Nginx的client_max_body_size。

Flask 上传文件大小超限直接 413 错误怎么办
Flask 默认对请求体大小不做限制,但底层 Werkzeug 会拦截超过 MAX_CONTENT_LENGTH 的请求,并返回 413 Request Entity Too Large。这个限制必须在应用初始化阶段就设置,**不能在路由里动态改**。
常见错误是只在视图里检查 request.files 大小,但此时文件已完整接收进内存或临时文件,起不到限流作用。
- 在
app = Flask(__name__)后立即设置:app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024(16MB) - 该值单位是字节,且对整个请求体生效(含表单字段、多个文件等)
- 若用 Nginx 或其他反向代理,还需同步配置
client_max_body_size,否则请求会在代理层就被拒,Flask 根本收不到
如何安全地验证上传文件的 MIME 类型
仅靠 filename 后缀(如 .pdf)或 content_type 字段完全不可信——客户端可任意伪造。真正有效的检查必须基于文件头(magic bytes)。
推荐用 python-magic 库(libmagic 绑定),而非 imghdr 或 filetype(后者不支持所有 MIME 类型,且部分场景误判率高)。
立即学习“Python免费学习笔记(深入)”;
- 安装:
pip install python-magic(Linux/macOS 通常需额外装libmagic;Windows 用户建议用python-magic-bin) - 验证示例:
import magic<br>mime = magic.Magic(mime=True)<br>mimetype = mime.from_buffer(file.stream.read(2048))<br>file.stream.seek(0) # 记得重置指针
- 白名单应限定具体 MIME,比如
'image/jpeg',避免宽泛匹配'image/*'(可能绕过)
上传后保存前如何防止路径遍历攻击
用户提交的 filename 可能含 ../ 或绝对路径,直接拼接 os.path.join(upload_dir, filename) 会导致写入任意位置。
核心原则:**丢弃原始文件名,生成安全随机名,仅保留扩展名(且需再次校验)**。
- 用
secure_filename()(来自werkzeug.utils)处理原始名,但它只过滤路径分隔符,不防空字节或 Unicode 归一化绕过 - 更稳妥做法:
ext = os.path.splitext(filename)[1].lower(),再结合白名单确认是否允许该扩展名 - 最终文件名建议用
uuid.uuid4().hex + ext,避免依赖用户输入
大文件上传时内存占用过高怎么缓解
默认情况下,Flask 把整个文件读进内存(request.files['file'].read()),100MB 文件就会吃掉同等内存。生产环境必须流式处理。
关键点在于:**不要调用 .read() 或 .save(),而是用 stream 属性逐块读取**。
- 检查
file.content_length是否合理(虽可伪造,但配合MAX_CONTENT_LENGTH已有基础防护) - 用
for chunk in iter(lambda: file.stream.read(8192), b'')分块写入目标文件 - 若需校验哈希或扫描病毒,也应在流式读取过程中完成,避免二次加载
真正难的是平衡安全性与体验:MIME 检查要读前若干 KB,但又不能让整个文件进内存;路径处理要彻底剥离用户控制权,又得保留合法扩展名。这些细节漏掉一个,就可能变成漏洞入口。


















