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

React上传文件至Node后端无法访问File对象问题

问题描述

将React前端<input type="file">提交的FileList传递到Node后端时,浏览器控制台显示文件列表已作为表单数据提交,但Node端遍历的文件对象为空,无法获取文件名完成上传操作。

相关代码与输出

Node.js路由代码

router.post("", (req, res) => {
    
  var tempFiles = req.body.files;

  var fileCount = Object.keys(tempFiles).length;

  console.log("FileList Keys: " + Object.keys(tempFiles));
  console.log("Length: " + Object.keys(tempFiles).length);
  console.log("Object Length: " + Object.keys(tempFiles['0']).length);
  
  // Loop through files
  for (let i = 0; i < fileCount; i++) {

    let file = tempFiles[i];
    console.log(tempFiles[i]);

  }

}

Node控制台输出

FileList Keys: 0,1
Length: 2
Object Length: 0
{}
{}

React表单代码

import React from 'react';
import axios from 'axios';
import {useState} from 'react';
import { useForm } from "react-hook-form";
import { Stack, Input ,Button, FormControl } from '@chakra-ui/react';

import BasicBanner from '../../core/components/banners/BasicBanner';


export default function UploadEvidence(props) {
    
    const [formMessage, setFormMessage] = useState("");
    const { register, formState: { errors }, handleSubmit } = useForm();
    const onError = (errors, e) => console.log(errors, e);

    const onSubmit = (data, e) => {
        console.log(data);
        axios.post('http://localhost:5000/api/uploads', data)
        .then(function (response) {
            console.log(response);
            setFormMessage("Upload successful");
        })
        .catch(function (error) {
            console.log(error);
            setFormMessage("Error uploading");
        });
    }

    return (
        <form onSubmit={handleSubmit(onSubmit, onError)} enctype="multipart/form-data">
            
            <Stack spacing="10">
            {formMessage && 
                <BasicBanner message={formMessage} />
            }

            
            <Input
              type="file"
              accept="pdf/*"
              multiple
              {...register("files", {required: true })}
              aria-invalid={errors.files ? "true" : "false"}
              />

            </Stack>

            <FormControl mt={4}>
                <Button type="submit" colorScheme='blue'>Save</Button>
            </FormControl>

        </form>

    )
}

Node server.js代码

const express = require('express')
const PORT = process.env.PORT || 5000
const app = express()
const bodyParser = require("body-parser");
const fileupload = require("express-fileupload");
var cors = require('cors');

app.use(cors());
app.use(fileupload());
app.use(express.static("files"));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

// ... Routes ...
 
问题原因
  1. 数据序列化失效:axios默认将请求数据序列化为JSON格式,但File对象无法被JSON序列化,传递到后端后会被转化为空对象{}。
  2. 后端读取位置错误:你使用了express-fileupload中间件,上传的文件会被解析到req.files对象中,而非req.body,但当前代码从req.body.files读取数据,自然无法拿到有效文件信息。
解决方案

前端修改:使用FormData传递文件

在onSubmit函数中手动构建FormData,将文件对象正确存入后再发送请求,同时设置对应请求头:

const onSubmit = (data, e) => {
    const formData = new FormData();
    // 遍历FileList,将每个文件添加到FormData中
    Array.from(data.files).forEach(file => {
        formData.append('files', file);
    });
    
    axios.post('http://localhost:5000/api/uploads', formData, {
        headers: {
            'Content-Type': 'multipart/form-data'
        }
    })
    .then(function (response) {
        console.log(response);
        setFormMessage("Upload successful");
    })
    .catch(function (error) {
        console.log(error);
        setFormMessage("Error uploading");
    });
}

后端修改:从req.files读取文件

调整路由代码,从req.files中获取上传的文件:

router.post("", (req, res) => {
    // 处理单个/多个文件的情况:express-fileupload在单文件时返回对象,多文件时返回数组
    const tempFiles = req.files?.files || [];
    const filesArray = Array.isArray(tempFiles) ? tempFiles : [tempFiles];

    console.log("文件数量: " + filesArray.length);
    
    // 遍历文件获取信息并处理
    filesArray.forEach((file, index) => {
        console.log(`第${index+1}个文件名:`, file.name);
        // 执行文件保存操作,示例:file.mv(`./uploads/${file.name}`)
    });

    res.status(200).json({message: "文件接收成功"});
});
额外注意事项
  • 前端<form>标签的enctype="multipart/form-data"属性可保留,手动构建FormData时请求头会覆盖该属性,但不影响功能。
  • 确保express-fileupload中间件已正确安装并启用,无需调整其与bodyParser的注册顺序。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 15:35:28