React+PrimeReact文件上传至Flask后端时出现400 Bad Request错误
PrimeReact FileUpload 对接Flask后端400错误排查与解决
问题背景
使用PrimeReact的FileUpload组件实现文件上传,对接Flask后端时,无论使用axios还是fetch,均收到错误:400 Bad Request: The browser (or proxy) sent a request that this server could not understand.
前端代码(App.js)
import React, { useState, useEffect } from "react"; import { PrimeReactProvider, PrimeReactContext } from 'primereact/api'; import 'primereact/resources/themes/mira/theme.css'; import { FileUpload } from 'primereact/fileupload'; import axios from 'axios'; import './App.css'; function App() { const documentUploadHandler = ({files}) => { const [file] = files; uploadDoc(file); }; const uploadDoc = async (document) => { let formData = new FormData(); formData.append('document', document); try { let response = await axios.post('http://127.0.0.1:8000/api/upload', formData, { headers: { 'Content-Type': 'multipart/form-data' } }); let res = response.data; if (res.status !== 1) { alert('Error uploading file'); } else { alert('File uploaded successfully'); } } catch (error) { console.warn('Error uploading file:', error); alert('Error uploading file'); } }; return ( <PrimeReactProvider> <FileUpload name="document_upload" uploadHandler={documentUploadHandler} auto url={'/api/upload'} accept="image/*,application/pdf" maxFileSize={4000000} emptyTemplate={<p className="mt-[-7%]">Drag and drop files to here to upload.</p>} /> </PrimeReactProvider> ); } export default App;
后端代码(server.py)
from flask import Flask, request, jsonify from flask_cors import CORS from classify_doc import * app = Flask(__name__) CORS(app, origins="*") @app.route('/api/upload', methods=['POST']) def upload_file(): try: file = request.files['document'] print(f"Uploading document {file.filename}") return "done" except Exception as e: print(f"Couldn't upload document: {e}") return "failed" if __name__ == '__main__': app.run(port=8000, debug=True)
错误日志
Couldn't upload document: 400 Bad Request: The browser (or proxy) sent a request that this server could not understand. 127.0.0.1 - - [29/May/2024 17:54:06] "POST /api/upload HTTP/1.1" 200 -
排查与解决方法
核心问题分析
- 手动设置Content-Type导致解析失败:在axios请求中手动设置
Content-Type: multipart/form-data,但浏览器发送multipart请求时需要自动生成包含boundary(表单分隔符)的Content-Type头,手动设置会丢失boundary,导致Flask无法解析表单数据。 - FileUpload组件属性冲突:同时设置了
uploadHandler(自定义上传逻辑)和url(组件默认上传地址),会触发两次上传请求,造成逻辑混乱。
具体修复步骤
前端修复1:移除手动设置的Content-Type
修改uploadDoc函数中的axios请求配置,删除手动指定的headers,让浏览器自动生成正确的Content-Type:const uploadDoc = async (document) => { let formData = new FormData(); formData.append('document', document); try { // 移除headers配置,让浏览器自动处理Content-Type let response = await axios.post('http://127.0.0.1:8000/api/upload', formData); let res = response.data; if (res.status !== 1) { alert(`Error uploading file: ${res.message}`); } else { alert('File uploaded successfully'); } } catch (error) { console.warn('Error uploading file:', error); alert('Error uploading file'); } };前端修复2:移除冲突的url属性
修改FileUpload组件,删除url={'/api/upload'},只保留自定义的uploadHandler:<FileUpload name="document_upload" uploadHandler={documentUploadHandler} auto accept="image/*,application/pdf" maxFileSize={4000000} emptyTemplate={<p className="mt-[-7%]">Drag and drop files to here to upload.</p>} />后端修复:返回标准JSON响应
调整后端接口,使用jsonify返回结构化响应,方便前端统一处理:@app.route('/api/upload', methods=['POST']) def upload_file(): try: file = request.files['document'] print(f"Uploading document {file.filename}") return jsonify({"status": 1, "message": "done"}) except Exception as e: print(f"Couldn't upload document: {e}") # 错误时返回400状态码和错误信息 return jsonify({"status": 0, "message": str(e)}), 400
内容的提问来源于stack exchange,提问作者rainypuns
相关产品推荐
相关产品推荐

