必须确保HTML表单设enctype="multipart/form-data",否则request.files为空;后端用request.files.get('file')获取文件('file'为input的name值),保存前须用secure_filename()处理文件名、确保UPLOAD_FOLDER存在且用os.path.join构造路径。

Flask 中 request.files 怎么取到上传的文件
必须确保 HTML 表单设置了 enctype="multipart/form-data",否则 request.files 永远为空字典。Flask 不会报错,但你拿不到任何文件——这是最常被忽略的前提。
后端用法很简单:file = request.files.get('file'),其中 'file' 是表单里 <input type="file" name="file"> 的 name 属性值。如果前端用了多个文件输入或动态 name,得对应改 key。
- 如果没选文件,
file.filename是空字符串(不是None),别直接用它拼路径 -
file.filename可被客户端任意篡改,不能直接用于保存路径,尤其不能拼进os.path.join()后直接写磁盘 - 调用
file.save()前,务必先检查file.filename是否非空且合法
怎么安全地保存上传的文件(避免路径遍历和覆盖)
别信 file.filename,它可能包含 ../../etc/passwd 这类恶意路径。正确做法是提取原始文件名、清理扩展名、生成随机前缀,再拼接目标目录。
推荐用 secure_filename()(来自 werkzeug.utils),但它只处理 ASCII 字符,对中文名会清空成空字符串。如需支持中文,得自己写逻辑:保留字母数字下划线点号,替换其余为下划线,再截断过长部分。
- 永远用
os.path.join(UPLOAD_FOLDER, safe_name)构造保存路径,不要用字符串拼接 - 保存前检查
UPLOAD_FOLDER是否存在,不存在就os.makedirs() - 不建议直接覆盖同名文件,可加时间戳或 UUID 前缀,比如
f"{uuid4().hex}_{safe_name}"
上传大文件时为什么卡住或 413 错误
默认 Flask 限制请求体最大为 500KB,超限直接返回 413 Request Entity Too Large。这不是代码问题,是配置问题。
创建 Flask + Vue.js 全栈项目,采用单端口架构、uv 依赖管理、结构化日志和生产级前端设计。当用户要求以下操作时触发:创建新的 Flask+Vue 项目、搭建 Web 应用、构建全栈 Python+Vue 应用、初始化 Flask Web 项目、设置单端口 Flask 前后端项目。触发词:新建项目、创建项目、搭建项目、Flask项目、Vue项目。
有两个地方要调:app.config['MAX_CONTENT_LENGTH'] 控制整个请求体大小(包括表单字段+文件),单位是字节;Nginx 或其他反向代理也得同步调大 client_max_body_size,否则请求根本到不了 Flask。
- 设为
16 * 1024 * 1024(16MB)比较常见,按业务调整 - 设太大有内存风险:Flask 默认把整个文件读进内存,大文件上传会吃光内存
- 真要传 GB 级文件,得换流式处理(如用
file.stream.read(8192)分块读),并配 Nginx 的client_body_temp_path
怎么在上传后返回 JSON 而不是跳转页面
前端用 fetch 或 Axios 提交 FormData 时,后端必须返回 JSON,否则浏览器会尝试解析成 HTML 并跳转——哪怕你写了 return jsonify(...),只要前端没设 Content-Type 或没处理响应,就容易出问题。
关键点:后端用 jsonify(),前端用 response.json() 解析,且确保表单提交是异步的(阻止默认 submit 行为)。
- 别在
<form></form>上直接写action提交,那必跳转;要用 JS 拦截 - Flask 返回前,确保没有其他 print / print_debug 类语句干扰 JSON 格式
- 上传失败时也返回标准 JSON(如
{"error": "No file selected"}),前端统一处理
Flask 文件上传本身不复杂,但每个环节都卡在细节上:表单属性漏写、filename 直接拼路径、大小限制没配、前端没拦截默认行为……最容易出问题的,其实是前后端对“上传完成”这件事的理解不一致。

















