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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 06:20:34