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

React向Flask传递PDF时出现BadRequestKeyError问题排查

排查React fetch传PDF到Flask时的KeyError: 'file'问题及优化方案

问题原因分析

虽然后端能保存文件,但抛出KeyError: 'file',核心原因是前端传递的FormData键名与后端期望的'file'不匹配,或是请求头设置错误导致后端无法正确解析表单数据。常见触发场景:

  • 前端FormData添加文件时用了其他键名(比如'pdf'),但后端用request.files['file']获取
  • 手动设置了Content-Type: multipart/form-data请求头,导致浏览器无法自动生成正确的boundary分隔符,后端解析失败
  • 前端未正确将文件对象添加到FormData中

代码修正示例

React前端修正

确保FormData的键名是'file',且不手动设置Content-Type(让浏览器自动处理多表单数据的边界符):

const handleSubmit = async (e) => {
  e.preventDefault();
  if (!selectedFile) return;

  const formData = new FormData();
  // 键名必须和后端request.files['file']的键完全一致
  formData.append('file', selectedFile);

  try {
    const response = await fetch('/api/upload-pdf', {
      method: 'POST',
      body: formData
      // 不要手动设置Content-Type,浏览器会自动添加带boundary的正确头
    });
    if (!response.ok) throw new Error('请求失败');
    const result = await response.json();
    console.log('处理结果:', result);
  } catch (error) {
    console.error('上传失败:', error);
  }
};

Flask后端修正

先校验请求中是否存在目标文件,再执行后续逻辑,同时添加基础的文件校验:

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

app = Flask(__name__)
UPLOAD_FOLDER = './uploads'
os.makedirs(UPLOAD_FOLDER, exist_ok=True)
# 限制上传文件大小为10MB
app.config['MAX_CONTENT_LENGTH'] = 10 * 1024 * 1024

@app.route('/api/upload-pdf', methods=['POST'])
def upload_pdf():
    # 先检查请求中是否包含'file'字段
    if 'file' not in request.files:
        return jsonify({'error': '未上传任何文件'}), 400
    
    file = request.files['file']
    if file.filename == '':
        return jsonify({'error': '未选择文件'}), 400
    
    # 校验文件类型
    if not file.filename.lower().endswith('.pdf'):
        return jsonify({'error': '仅支持PDF格式文件'}), 400
    
    # 用secure_filename处理文件名,避免路径遍历攻击
    safe_filename = secure_filename(file.filename)
    file_path = os.path.join(UPLOAD_FOLDER, safe_filename)
    file.save(file_path)
    
    # 执行PDF解析逻辑(示例函数,需根据实际需求实现)
    parsed_data = parse_pdf_content(file_path)
    
    return jsonify({'data': parsed_data}), 200

def parse_pdf_content(file_path):
    # 示例解析逻辑,可替换为PyPDF2、pdfplumber等库的实际解析代码
    return {
        'filename': os.path.basename(file_path),
        'pages': 3,
        'content': '提取的PDF文本内容示例'
    }

# 捕获文件过大的异常
@app.errorhandler(413)
def request_entity_too_large(error):
    return jsonify({'error': '文件大小超过限制(最大10MB)'}), 413

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

更优实现方式

  1. 前端侧增强

    • 添加文件大小、类型的前置校验,提前拦截不符合要求的文件
    • 实现上传进度显示:利用fetch结合ReadableStream监听上传进度,给用户直观反馈
    • 完善错误处理:区分网络错误、后端返回的业务错误(如文件过大、格式不符),给出对应提示
  2. 后端侧增强

    • 异步处理PDF解析:如果解析耗时较长,用Celery等异步任务队列,避免阻塞HTTP请求,返回任务ID让前端轮询结果
    • 添加日志记录:记录上传文件的名称、大小、处理状态、错误信息,方便后续排查问题
    • 定期清理上传文件:设置定时任务,清理超过保留期限的临时PDF文件,避免磁盘空间占用过多

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 00:55:34