Node.js,multer和req.body为空

40

这是我的问题,我有一个表单,可以插入文件和字段,但我只收到文件而不是参数test!为什么?

这是我的代码:

app.js:

var express = require('express');
var bodyParser = require('body-parser');
var app = express();
var port = 8000;
var multer = require('multer'); // v1.0.5
var storage =   multer.diskStorage({
  destination: function (req, file, callback) {
    callback(null, './uploads');
  },
  filename: function (req, file, callback) {
    callback(null, file.originalname.substring(0,file.originalname.lastIndexOf('.')) + '-' + Date.now() + file.originalname.substring(file.originalname.lastIndexOf('.'),file.originalname.length));
  }
});
var upload = multer({ storage : storage}).single('fileUpload');

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));

app.post('/api/upload',function(req,res){
    console.log(req.body);
    upload(req,res,function(err) {
        if(err) {
            return res.end("Error uploading file.");
        }
        res.end("File is uploaded");
    });
});

app.listen(port, function () {
    console.log('Express server inizializzato sulla porta ' + port);
});

index.html:

<html>
    <head>
        <title>Test upload</title>
    </head>
    <body>
        <form name="form" action="http://localhost:8000/api/upload" method="post" enctype="multipart/form-data">
            <input type="text" name="test" />
            <input type="file" name="fileUpload" />
            <input type="submit" value="invia" />
        </form>
    </body>
</html>

有人可以帮助我吗?


你尝试过使用 req.body 吗? - abdulbarik
@abdulbarik:是的,我尝试返回req.body但是返回了{}。 - Filippo1980
1
这可能会有所帮助:https://dev59.com/FVsV5IYBdhLWcg3wuxCM - abdulbarik
1
@abdulbarik 谢谢,我尝试过了但仍然没变化,不管怎样就像我在回答中所写的,我通过将请求移动到上传函数中解决了问题...为什么会出现这个问题呢?我不知道,重要的是现在它可以工作了! - Filippo1980
6个回答

86

2017年更新

来自Readme

请注意,req.body可能尚未完全填充。它取决于客户端将字段和文件传输到服务器的顺序。

我通过在前端反转表单对象属性的顺序解决了我的问题:

    var newFormObj  = new FormData();
    newFormObj.append('internalUserID', internalUserID);
    newFormObj.append('listingImage', this.binaryImages[image]);

在后端:

var storage = multer.diskStorage({
  destination: function (req, file, cb) {
    console.log(req.body.internalUserID) // YAY, IT'S POPULATED
    cb(null, 'listing-pics/')
  },                    
  filename: function (req, file, cb) {
    cb(null, file.fieldname + '-' + Date.now())
  }                     
});                     

var upload = multer({ storage: storage });

2
为什么我的req.body是空的? - leafiy
3
我在使用Postman测试API时遇到了同样的问题,将文件上传字段排在最后解决了这个问题。谢谢! - Ellery Familia
我是唯一一个觉得这个上下文很奇怪的人吗? - Tarik Merabet
1
如果我遇到了与DiskStorage()相同的memoryStorage()问题,该怎么办? - Prasanna
兄弟,你做得太好了,非常感谢。 - MBK
显示剩余2条评论

38

您需要重新调整前端请求中的字段顺序,下面我将进行解释:

我正在我的nodejs应用程序中使用multer上传多个文件和单个文件。

Postman请求截图 (错误方法): 输入图像描述

Postman请求截图 (正确方法): 输入图像描述

请注意字段顺序的不同。始终在请求内容的末尾附加媒体文件。

我花了近2个小时才找到这个问题。 肯定有效。只需尝试即可。


你的Node代码长什么样?你是否使用了中间件request.body? - Abdennour TOUMI
谢谢,我学到了一个关键的东西:“在请求内容的末尾附加媒体文件”。 - Akin Zeman

15

我解决了将req.body移到post函数的末尾:

app.post('/api/upload?:test',function(req,res){

    upload(req,res,function(err) {
        if(err) {
            return res.end("Error uploading file.");
        }
        res.end("File is uploaded");
    console.log(req.body);

    });
});

如果有人能告诉我为什么,我很高兴学到新的东西!但是,现在我已经解决了!


它完美地运行了,但为什么?有人能解释一下吗? - Frank Fang
12
嗨,body-parser无法处理multipart/form-data格式的请求体,但multer可以。这就是为什么你只能在上传函数内访问req.body的原因。 - Angie
@Angie,请考虑将您的评论提交为答案,它是解决我的问题的方法。 - Tunji_D

1

console.log(req.body)移至upload(req,res,function(err) {...})内部。

默认的express body-parser无法处理multipart/form-data,因此我们使用multer来解析form-data,该解析器可以在您的upload函数中访问。


1

您可以使用JavaScript手动重新排序字段,以确保在文件之前发送字段。


0
如果有人遇到像下面这样稍微复杂一些的初始布局,将上传功能移动到每个路由文件中并在那里使用它们似乎已经解决了我的问题。为什么会这么反复无常,我不知道,老实说这让我头痛不已。
需要注意的是,我有一个自定义存储引擎,它将文件流式传输到磁盘上,这可能导致了这个问题,但它只发生在一个特定的路由上,而其他几个在功能上完全相同的路由却可以完美地工作。
希望这能在某一天帮助到其他人。

初始应用程序布局

app.ts


import express from 'express';
import multer from 'multer';

import profilePicture from './routes/profile-picture.ts';

const upload = multer();

class Server {
    constructor() {
        this.app = express()
    }

    setRoutes() {
        this.app.use( '/upload', upload.single( 'profile' ), profilePicture );
    }

    // ... other methods
}

profile-picture.ts

import { Router } from 'express';

const profilePicture = Router();

profilePicture.post( '/', ( req, res, next ) => {
    console.log( req.body ); // This was always empty, regardless of field order
    // do something with req
}

更新的布局,不知何故有效

app.ts

import express from 'express';

import profilePicture from './routes/profile-picture.ts';


class Server {
    constructor() {
        this.app = express()
    }

    setRoutes() {
        this.app.use( '/upload', profilePicture );
    }

    // ... other methods
}

profile-picture.ts

import { Router } from 'express';
import multer from 'multer';

const upload = multer();

const profilePicture = Router();

profilePicture.post( '/', upload.single( 'profile' ), ( req, res, next ) => {
    console.log( req.body ); // No longer empty, hooray!
    // do something with req
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接