Flask 文件上传 400 错误排查与正确实现指南

千婷大大_7264

千婷大大_7264

2026-10-25

244人浏览

原创

Flask 文件上传 400 错误排查与正确实现指南

本文详解 flask + html + javascript 文件上传中出现 400 bad request 的根本原因,指出 formdata 构建不当与后端键名不匹配是主因,并提供完整、可运行的前后端协同解决方案。

本文详解 flask + html + javascript 文件上传中出现 400 bad request 的根本原因,指出 formdata 构建不当与后端键名不匹配是主因,并提供完整、可运行的前后端协同解决方案。

在使用 Flask 构建文件上传功能时,前端通过 <input type="file"> 选择文件、JavaScript 使用 FormData 提交,而后端用 request.files 接收——这一看似标准的流程,却极易因一个关键细节出错而触发 400 Bad Request。该错误通常并非网络或服务器配置问题,而是前后端对表单字段名称(field name)和数据结构的约定不一致所致。

? 根本原因分析

原始代码中存在两个关键缺陷:

  1. 前端 FormData 构建方式错误:
    new FormData(this) 试图直接从表单元素创建 FormData,但若该表单(#userInputYaml)并未包含 id="inputYaml" 的 <input> 子元素(例如 input 是表单外独立存在的),则 this 指向的表单内无 file input,导致 formData 实际为空;即使 DOM 结构正确,<input type="file"> 默认不会自动加入 FormData(尤其当未设置 name 属性或未触发 change 事件时),必须显式读取 files 并 append。

  2. 后端键名与前端不匹配:
    前端 HTML 中 <input name="inputYaml"> 指定字段名为 "inputYaml",但后端却尝试用 files['inputYaml'] 访问——这本身逻辑正确;然而原始 JS 代码中 new FormData(this) 极可能未成功捕获该 input,导致后端收到空 files 字典,files['inputYaml'] 抛出 KeyError,Flask 默认返回 400。

✅ 正确做法:前端显式获取 FileList 并 append,后端严格按 append 的 key 名取值。

Auth0 Flask
Auth0 Flask

在Flask应用中使用基于会话的身份验证实现登录、登出和用户资料,集成auth0-server-python进行服务端渲染

下载

✅ 正确实现(前后端完整示例)

▪ 前端 HTML + JavaScript

确保文件 input 具有 name 属性,并置于表单内(或独立处理):


JavaScript 改写为显式构建 FormData:

document.getElementById('userInputYaml').addEventListener('submit', function(event) {
  event.preventDefault();

  const fileInput = document.getElementById('inputYaml');
  const file = fileInput.files[0]; // 单文件上传,取第一个

  if (!file) {
    alert('Please select a file.');
    return;
  }

  const formData = new FormData();
  formData.append('inputYaml', file); // ✅ 键名必须与后端 request.files['inputYaml'] 严格一致

  fetch('/submit', {
    method: 'POST',
    body: formData // ✅ 不要加 headers: { 'Content-Type': ...' } —— 浏览器会自动设置 multipart/form-data 及 boundary
  })
  .then(response => {
    if (!response.ok) throw new Error(`HTTP ${response.status}`);
    return response.json();
  })
  .then(data => {
    alert('Upload successful!');
    this.reset(); // 重置表单
  })
  .catch(error => {
    console.error('Upload failed:', error);
    alert('Upload failed: ' + error.message);
  });
});

▪ 后端 Flask(增强健壮性)

import os
from flask import Flask, request, jsonify
from werkzeug.utils import secure_filename

app = Flask(__name__)

def save_file(file, path):
    try:
        os.makedirs(os.path.dirname(path), exist_ok=True)
        file.save(path)
    except Exception as e:
        raise RuntimeError(f"Failed to save file {file.filename}: {str(e)}")

@app.route('/submit', methods=['POST'])  # ⚠️ 注意:原代码中 method=['POST'] 缺少 's',且括号为中文
def submit_files():
    # ✅ 显式检查是否存在 inputYaml 字段
    if 'inputYaml' not in request.files:
        return jsonify({'error': 'No file part in request'}), 400

    yaml_file = request.files['inputYaml']

    # ✅ 检查用户是否实际选择了文件(避免空 filename)
    if yaml_file.filename == '':
        return jsonify({'error': 'No selected file'}), 400

    # ✅ 安全验证文件扩展名(防止伪造 Content-Type)
    filename = secure_filename(yaml_file.filename)
    if not (filename.lower().endswith(('.yaml', '.yml'))):
        return jsonify({'error': 'Invalid file extension. Only .yaml or .yml allowed.'}), 400

    # ✅ 构建安全保存路径(避免路径遍历)
    save_path = os.path.join('/path/to/save', filename)

    try:
        save_file(yaml_file, save_path)
        return jsonify({'message': 'File uploaded successfully', 'filename': filename}), 200
    except Exception as e:
        return jsonify({'error': str(e)}), 500

⚠️ 关键注意事项

  • 不要手动设置 Content-Type 头:fetch 发送 FormData 时,浏览器会自动生成正确的 multipart/form-data 及 boundary;手动设置会导致解析失败。
  • 始终使用 secure_filename():防止恶意文件名(如 ../../etc/passwd)造成路径遍历漏洞。
  • 前端校验 ≠ 后端校验:HTML 的 accept=".yaml" 仅作浏览器提示,可被绕过;后端必须重新验证扩展名与内容。
  • 调试技巧:在 Flask 路由开头添加 print(request.files) 和 print(request.form),确认实际接收的数据结构。

遵循以上方案,即可彻底解决 Flask 文件上传中的 400 Bad Request 问题,构建安全、可靠、符合生产要求的文件处理流程。

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

flask

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
html版权符号
html版权符号

html版权符号是“©”,可以在html源文件中直接输入或者从word中复制粘贴过来,php中文网还为大家带来html的相关下载资源、相关课程以及相关文章等内容,供大家免费下载使用。

2023.06.14

6575

7

html在线编辑器
html在线编辑器

html在线编辑器是用于在线编辑的工具,编辑的内容是基于HTML的文档。它经常被应用于留言板留言、论坛发贴、Blog编写日志或等需要用户输入普通HTML的地方,是Web应用的常用模块之一。php中文网为大家带来了html在线编辑器的相关教程、以及相关文章等内容,供大家免费下载使用。

2023.06.21

3652

4

html网页制作
html网页制作

html网页制作是指使用超文本标记语言来设计和创建网页的过程,html是一种标记语言,它使用标记来描述文档结构和语义,并定义了网页中的各种元素和内容的呈现方式。本专题为大家提供html网页制作的相关的文章、下载、课程内容,供大家免费下载体验。

2023.07.31

3330

5

html空格
html空格

html空格是一种用于在网页中添加间隔和对齐文本的特殊字符,被用于在网页中插入额外的空间,以改变元素之间的排列和对齐方式。本专题为大家提供html空格的相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.01

3359

5

html是什么
html是什么

HTML是一种标准标记语言,用于创建和呈现网页的结构和内容,是互联网发展的基石,为网页开发提供了丰富的功能和灵活性。本专题为大家提供html相关的各种文章、以及下载和课程。

2023.08.11

5019

6

html字体大小怎么设置
html字体大小怎么设置

在网页设计中,字体大小的选择是至关重要的。合理的字体大小不仅可以提升网页的可读性,还能够影响用户对网页整体布局的感知。php中文网将介绍一些常用的方法和技巧,帮助您在HTML中设置合适的字体大小。

2023.08.11

3301

3

html转txt
html转txt

html转txt的方法有使用文本编辑器、使用在线转换工具和使用Python编程。本专题为大家提供html转txt相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.31

3109

3

html文本框代码怎么写
html文本框代码怎么写

html文本框代码:1、单行文本框【<input type="text" style="height:..;width:..;" />】;2、多行文本框【textarea style=";height:;"></textare】。

2023.09.01

2708

6

HTML嵌入CSS样式的方法
HTML嵌入CSS样式的方法

HTML嵌入CSS样式的方法有内联样式、内部样式表和外部样式表。本专题为大家提供CSS样式相关的文章、下载、课程内容,供大家免费下载体验。

2023.09.20

2808

5

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Flask-Migrate数据库迁移文档
Flask-Migrate数据库迁移文档

共0课时 | 0人学习

Flask官方快速入门文档
Flask官方快速入门文档

共0课时 | 0人学习