You need to enable JavaScript to run this app. Node.js使用Multer上传图片时req.body为空无法获取表单字段数据
优惠活动
大模型
产品
解决方案
定价
更多

Node.js使用Multer上传图片时req.body为空无法获取表单字段数据

问题现象

Node.js项目使用Multer实现图片上传功能时,图片可正常完成上传,但无法从req.body获取表单内的文本输入字段数据,打印req.body得到空对象{}。经测试,移除表单的enctype="multipart/form-data"属性后req.body可正常返回数据,但此时图片无法上传。

现存代码

前端表单

<form action="/postRoute" method="POST" enctype="multipart/form-data">
    <div class="form-group row">
        <div class="col-sm-6 mb-3 mb-sm-0">
            <input type="text" placeholder="Title" name="title">
        </div>
        <div class="col-sm-6">
            <input type="text" placeholder="Description" name="description">
        </div>
    </div>
    <div class="file-field input-field">
        <div class="btn grey">
            <span>Image</span>
            <input type="file" name="image" multiple>
        </div>
    </div>
    <button type="submit" class="btn btn-primary btn-user btn-block">
        List
    </button>
</form>

路由处理逻辑

router.post('/postRoute', (req, res) => {
    console.log(req.body);

    upload(req, res, (err) => {
        if(err) {
         throw err;   
        } else {
            console.log('logging files');
            console.log(req.files);

            if(req.files.length <= 0) {
                res.render('listing', {
                    msg: 'Error: No File Selected!'
                })
            } else {
                let list = Listing();
                list.title = title;
                list.description = description;
                list.photos = req.files[0].filename
                
                list.save((err) => {
                    if(err) throw err;
            
                    req.flash('success', 'Product Listed Successfully!')
                    res.redirect('/')
                })
            }
        }
    })
})

Multer配置

//Set Storage Engine
const storage = multer.diskStorage({
    destination: './public/uploads/',
    filename: function(req, file, cb) {
        cb(null, file.fieldname + '-' + Date.now() + path.extname(file.originalname));
    }
})

//Init Upload
const upload = multer({
    storage: storage,
    llmits: {fileSize: 1000000},
    fileFilter: (req, file, cb) => {
        checkFileType(file, cb);
    }
}).array('image')

//Check File Type
function checkFileType (file, cb) {
    //Allowed ext
    const fileType = /jpeg|jpg|png|gif/;

    //Check ext
    const extname = fileType.test(path.extname(file.originalname).toLowerCase());

    //Check Mime
    const mimetype = fileType.test(file.mimetype)

    if(mimetype && extname) {
        return cb(null, true);
    } else {
        cb('Error: Images Only!');
    }
}

根因分析

Express内置的express.urlencoded中间件仅能解析application/x-www-form-urlencoded格式的请求,无法处理multipart/form-data格式的请求体。Multer的解析逻辑是流式处理请求,处理完成后才会把文本字段挂载到req.body上:

  • 在调用upload()方法之前就读取/打印req.body,此时Multer还未开始解析请求流,拿到的自然是空对象
  • 路由代码中直接引用了未定义的title、description变量,没有从req.body中取值
  • Multer配置中参数名拼写错误,llmits应为limits,导致文件大小限制不生效

修复方案

  1. 确认项目入口文件正确配置基础解析中间件(若已配置可跳过):
// 项目入口app.js/index.js
app.use(express.urlencoded({ extended: false }));
app.use(express.json());
  1. 调整路由逻辑,所有req.body、req.files的取值必须放在Multer解析完成后执行,不要在调用upload前读取请求体:
    推荐使用Express中间件写法,逻辑更简洁:
router.post('/postRoute', upload, (req, res) => {
    // 解析完成后可直接读取req.body、req.files
    console.log(req.body); // 可正常获取title、description字段
    console.log(req.files); // 可正常获取上传的文件列表

    if (req.files.length <= 0) {
        return res.render('listing', {
            msg: 'Error: No File Selected!'
        })
    }

    // 正确从req.body中取值,替换原来未定义的变量
    const list = new Listing();
    list.title = req.body.title;
    list.description = req.body.description;
    list.photos = req.files[0].filename;

    list.save((err) => {
        if (err) throw err;
        req.flash('success', 'Product Listed Successfully!')
        res.redirect('/')
    })
})
若保留手动调用upload的写法,必须把取值逻辑放到upload的回调内部:
router.post('/postRoute', (req, res) => {
    // 禁止在这里读取req.body!此时未解析
    upload(req, res, (err) => {
        if (err) throw err;
        // 解析完成后再读取req.body
        const { title, description } = req.body;
        // 后续业务逻辑...
    })
})
  1. 修正Multer配置中的拼写错误:
const upload = multer({
    storage: storage,
    // 修正llmits为limits
    limits: { fileSize: 1000000 },
    fileFilter: (req, file, cb) => {
        checkFileType(file, cb);
    }
}).array('image')

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.13 04:06:08