React+Express本地文件上传问题:FormData未定义等疑问求助
问题分析与修复方案
你的代码存在几个核心问题,导致文件上传失败并出现FormData is not defined错误,以下是逐部分的修复:
一、React组件:直接传递文件对象,无需FileReader
不需要用FileReader把文件转成DataURL,FormData可以直接append原生的File对象,这样更高效也避免数据格式混乱:
import React, { useContext } from 'react'; import MyContext from '../../context/MyContext'; function FileUploadPage({ param }) { const { createFileUpload } = useContext(MyContext); const changeHandler = (event) => { const file = event.target.files[0]; if (!file) return; const formData = new FormData(); formData.append("file", file); // 直接append文件对象,不是DataURL createFileUpload(formData); }; return ( <div> <input type="file" name="file" onChange={changeHandler} /> </div> ); } export default FileUploadPage;
二、Context:修正fetch请求的配置
之前把FormData转成JSON并设置Content-Type: application/json,这会破坏FormData的结构。正确的做法是直接把FormData作为请求body,浏览器会自动设置正确的Content-Type: multipart/form-data(包含boundary):
import { createContext, useState, useContext } from "react"; const MyContext = createContext(); const baseURL = "http://localhost:你的后端端口号"; // 替换成实际端口 export const MyContextProvider = ({ children }) => { async function APIRequest(body, endpoint) { const requestOptions = { method: "POST", body: body, // 直接传FormData,不需要JSON.stringify // 不要手动设置Content-Type,浏览器会自动处理 }; const response = await fetch(`${baseURL}${endpoint}`, requestOptions); const data = await response.json(); return data; } const createFileUpload = async (fileFormData) => { let response = await APIRequest(fileFormData, "/catalog/files/upload"); console.log(response); }; return ( <MyContext.Provider value={{ createFileUpload }}> {children} </MyContext.Provider> ); };
三、Express后端:解决FormData未定义并处理文件上传
Node.js环境中没有原生的FormData对象,而且Express默认无法解析multipart/form-data格式的请求,需要用multer中间件来处理文件上传(这是Express生态处理文件上传的标准方案):
1. 安装multer
npm install multer
2. 修改后端代码
const multer = require('multer'); const asyncHandler = require('express-async-handler'); const fs = require('fs'); const path = require('path'); // 确保uploads文件夹存在,避免报错 const uploadDir = './uploads'; if (!fs.existsSync(uploadDir)) { fs.mkdirSync(uploadDir); } // 配置multer,指定文件保存路径和文件名 const storage = multer.diskStorage({ destination: function (req, file, cb) { cb(null, uploadDir); }, filename: function (req, file, cb) { // 自定义文件名,避免重名 cb(null, Date.now() + '-' + file.originalname); } }); const upload = multer({ storage: storage }); // 注意要加上upload.single('file')中间件,对应前端FormData里的key const createFileUpload = asyncHandler(async (req, res) => { // 文件已经被multer保存到uploads文件夹,req.file包含文件信息 if (!req.file) { return res.status(400).json({ message: "未上传文件" }); } console.log('上传的文件信息:', req.file); res.status(200).json({ message: "文件上传成功", filePath: req.file.path, fileName: req.file.filename }); }); // 路由配置要挂载中间件 app.post('/catalog/files/upload', upload.single('file'), createFileUpload);
关键注意点
- 前端不要手动设置
Content-Type为multipart/form-data,浏览器会自动添加正确的boundary参数,否则后端无法解析 - 后端必须用multer处理
multipart/form-data请求,Express默认只能解析application/json和application/x-www-form-urlencoded - 确保后端的
uploads文件夹存在,可手动创建或通过代码自动生成
内容的提问来源于stack exchange,提问作者jason
相关产品推荐
相关产品推荐

