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

求助:Flask无法识别前端上传文件的问题如何解决

Flask无法接收前端上传文件的解决方案

问题场景

前端通过XMLHttpRequest上传文件后,Flask后端无法识别上传的内容,控制台输出如下:

ImmutableMultiDict([])
ImmutableMultiDict([])
b''
400 Bad Request: The browser (or proxy) sent a request that this server could not understand.

涉及的代码如下:

前端HTML

<input class="input" type="file" name="file" id="imageInp"></input>
<button class="addBtn" id="addBtn">Add</button>

原前端JS

var HttpClient = function () {
  this.get = function (aUrl, img) {
    var anHttpRequest = new XMLHttpRequest();
    var fdata = new FormData();
    fdata.append("file", img);

    anHttpRequest.open("POST", aUrl, true);
    anHttpRequest.setRequestHeader("Content-type", "multipart/form-data");
    anHttpRequest.send(fdata);
  }
}

document.getElementById("addBtn").onclick = function() { 
  image = document.getElementById("imageInp").files[0];
  var client = new HttpClient();
  client.get(*url_here*, image);
}

原Flask后端

@app.route('*url_here*', methods=['POST'])
def foo():
  try:
    print(request.form)
    print(request.files)
    print(request.data)
    frame = request.files['file'].read()
    
    return 'OK', 200, {'ContentType':'application/json'}

  except Exception as e:
    log('Main', e)
    return 'Error', 400, {'ContentType':'application/json'}

错误原因

  1. 手动设置Content-Type破坏请求结构:使用FormData时,浏览器会自动生成包含boundary的multipart/form-data请求头(例如multipart/form-data; boundary=----WebKitFormBoundaryxyz),这个boundary是分隔表单数据的关键标识。手动设置Content-type会丢失该标识,导致Flask无法解析请求体。
  2. 路由格式错误:Flask的路由URL必须以/开头,否则无法正确匹配请求路径。
  3. 变量未声明:前端的image变量未用var/let声明,虽不直接导致上传失败,但属于不良编码习惯。

修复步骤

1. 修正前端JS代码

  • 移除手动设置Content-type的代码
  • 为image变量添加声明
  • 修正函数名(避免get和POST请求语义冲突)

修改后的JS代码:

var HttpClient = function () {
  this.post = function (aUrl, img) {
    var anHttpRequest = new XMLHttpRequest();
    var fdata = new FormData();
    fdata.append("file", img);

    anHttpRequest.open("POST", aUrl, true);
    // 移除手动设置Content-type的行,由浏览器自动生成
    anHttpRequest.send(fdata);
  }
}

document.getElementById("addBtn").onclick = function() { 
  let image = document.getElementById("imageInp").files[0];
  if (!image) {
    alert("请先选择文件");
    return;
  }
  var client = new HttpClient();
  client.post('/upload', image); // 替换为实际后端接口路径
}

2. 修正Flask后端代码

  • 修正路由URL格式(以/开头)
  • 添加文件存在性检查,避免直接读取不存在的文件报错

修改后的Flask代码:

from flask import Flask, request, jsonify
import logging

app = Flask(__name__)
logging.basicConfig(level=logging.INFO)
log = logging.getLogger('Main')

@app.route('/upload', methods=['POST'])
def foo():
  try:
    print(request.form)
    print(request.files)
    print(request.data)
    
    # 检查文件是否存在
    if 'file' not in request.files:
      return jsonify({'error': '未上传文件'}), 400
    
    file = request.files['file']
    if file.filename == '':
      return jsonify({'error': '未选择文件'}), 400
    
    frame = file.read()
    print(f"接收文件大小:{len(frame)} 字节")
    
    return jsonify({'status': 'OK'}), 200

  except Exception as e:
    log.error('错误信息:%s', e)
    return jsonify({'error': str(e)}), 400

if __name__ == '__main__':
  app.run(debug=True)

验证结果

修改完成后,选择文件点击Add按钮,后端控制台会输出类似内容:

ImmutableMultiDict([])
ImmutableMultiDict([('file', <FileStorage: 'test.jpg' ('image/jpeg')>)])
b'\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01\x00\x00\x01\x00\x01\x00\x00\xff\xdb\x00C\x00\x08\x06\x06\x07\x06\x05\x08\x07\x07\x07\t\t\x08\n\x0c\x14\r\x0c\x0b\x0b\x0c\x19\x12\x13\x0f...'
接收文件大小:12345 字节

此时Flask可正常接收并读取上传文件,返回200 OK响应。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 20:06:19