req.body帖子为空


255

突然,这已经发生在我所有的项目中。

每当我使用express和body-parser在nodejs中发帖时,它req.body都是一个空对象。

var express    = require('express')
var bodyParser = require('body-parser')

var app = express()

// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded())

// parse application/json
app.use(bodyParser.json())

app.listen(2000);

app.post("/", function (req, res) {
  console.log(req.body) // populated!
  res.send(200, req.body);
});

通过ajax和邮递员,它总是空的。

但是通过卷曲

$ curl -H "Content-Type: application/json" -d '{"username":"xyz","password":"xyz"}' http://localhost:2000/

它按预期工作。

我尝试Content-type : application/json在前者中手动设置,但随后我总是得到400 bad request

这让我发疯。

我以为是人体分析器中有一些更新,但是我降级了,但没有帮助。

任何帮助表示赞赏,谢谢。


16
因此,您尝试过明确设置Content-Type邮递员身份吗?如果没有,您可以尝试一下,因为我以前遇到过邮递员不发送的问题Content-Type
mscdex

是的,我做到了。那就是我收到400:无效的json
约瑟夫·戴利,2014年

@mscdex-谢谢,我没有在邮递员中设置内容标签,而是发疯了:)
Muzafar Ali

对于那些来这里的人是因为他们希望从自己的API 发送/上传文件,因此必须使用表单数据。您需要一些处理表单数据的方法:npmjs.com/package/multer是非常流行的软件包。
bhaskar '19

无论如何,邮递员对整数和浮点值的处理都不太好。如果您使用整数或浮点值,请确保对所有内容(包括键和值)都加双引号
anabeto93

Answers:


272

在内容类型可用的3个选项的邮递员中,选择“ X-www-form-urlencoded”,它应该可以工作。

另外,为了消除错误消息,请替换:

app.use(bodyParser.urlencoded())

带有:

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

参见https://github.com/expressjs/body-parser

“ body-parser”中间件仅处理JSON和urlencoded数据,而不是多部分


这对邮递员很有用,我不确定为什么它可以与ajax一起使用,因为我没有做任何更改。
约瑟夫·戴利,2014年

出于某种原因,通过Angular发出的http帖子不需要进行URL编码,但是ajax调用可以。有人知道为什么吗?
youngrrrr '16

这对我有用,但是为什么不与原始编码一起使用呢?
Daniel Kobe

9
现在body-parser内置了express.js,可以使用app.use(express.json());
Sujeet Agrahari

非常感谢!尽管回答了很长时间,但它仍然有意义。
Spray'n'Pray

217

使用Postman,要使用原始JSON数据有效负载测试HTTP发布操作,请选择raw选项并设置以下标头参数:

Content-Type: application/json

另外,请确保将用作JSON有效负载中的键/值的所有字符串都用双引号引起来。

body-parser软件包将解析多行原始JSON有效负载。

{
    "foo": "bar"
}

在具有Postman v0.8.4.13扩展名(body-parserv1.12.2和expressv4.12.3)的Chrome v37和v41中通过以下设置进行了测试:

var express = require('express');
var app = express();
var bodyParser = require('body-parser');

// configure the app to use bodyParser()
app.use(bodyParser.urlencoded({
    extended: true
}));
app.use(bodyParser.json());

// ... Your routes and methods here

邮差原始JSON负载


哦,天哪,我怎么想念我粘贴了JS对象文字而不是正确格式化的JSON对象...:-S ...谢谢朋友!
Wes Johnson

用双引号将所有用作键/值的字符串包装起来...容易错过,但否则会破坏交易!谢谢。
loxyboi

截图的良好用法。
Xan-Kun Clark-Davis

当使用form-data在邮差后的数据,我总是得到{}的req.body。我应该设置 Content-Type选项吗?
mingchau

56

我犯了一个非常愚蠢的错误,忘记了为namehtml文件中的输入定义属性。

所以代替

<input type="password" class="form-control" id="password">

我有这个。

<input type="password" class="form-control" id="password" name="password">

现在request.body填充如下:{ password: 'hhiiii' }


1
am 那就是问题所在。谢谢!
马特·韦斯特

正是我的问题,没有名称值的表单输入花了数小时试图找出答案。谢谢。
karensantana

37

我发现,使用内容类型发送时可以使用

“应用程序/ json”

与服务器端结合

app.use(bodyParser.json());

现在我可以通过发送

var data = {name:"John"}
var xmlHttp = new XMLHttpRequest();
xmlHttp.open("POST", theUrl, false); // false for synchronous request
xmlHttp.setRequestHeader("Content-type", "application/json");
xmlHttp.send(data);

结果可以在request.body.name服务器上找到。


感谢您的支持。我确实认为这是最干净的解决方案,尽管不是最简单的解决方案,因为无论如何您都应该发送正确的内容类型。我认为。
Xan-Kun Clark-Davis

这就是答案!
凝胶

就我而言,我不得不将其更改为xmlHttp.send(JSON.stringify(data));
endo64 '19

18

我今天遇到了这个问题,而在Postman中删除content-type标头的问题已解决了!很奇怪。在这里添加它以防有人帮助。

我在这里关注BeerLocker教程:http://scottksmith.com/blog/2014/05/29/beer-locker-building-a-restful-api-with-node-passport/


2
我遇到过同样的问题。仅具有标题“ unchecked”(并且变灰)是不够的,我必须将其完全删除。即使“ </>”源按钮显示我没有以Content-Type处于未检查状态发送该标头,仍需要将其完全删除。
TheRemix

我不知道如何删除邮递员chrome扩展程序中的默认标题...您是否正在使用该应用程序?
WestleyArgentum

哦,我安装了该应用程序,它比扩展程序好得多。对不起,噪音。
WestleyArgentum

12

您必须检查正文解析器中间件是否已正确设置为请求的类型(json,urlencoded)。

如果已经设定,

app.use(bodyParser.json());

然后在邮递员中,您必须将数据作为原始数据发送。

https://i.stack.imgur.com/k9IdQ.png邮递员屏幕截图

如果已经设定,

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

然后应选择“ x-www-form-urlencoded”选项。


两者都怎么样?(bodyParser.urlencoded和bodyParser.json())...我可以在邮递员中使用哪一个?
TommyLeong

9

我的问题是我先创建路线

// ...
router.get('/post/data', myController.postHandler);
// ...

并在路由注册中间件

app.use(bodyParser.json());
//etc

由于应用程序的结构和示例中的复制和粘贴项目。

一旦我确定了在路由之前注册中间件的命令,它就可以工作。


感谢菲亚特,以正确的顺序使用了原始标签,终于为我工作了
Alex

4

即使当我第一次开始通过Web应用程序学习Node.js时,我仍然以自己的形式很好地完成了所有这些工作,但我仍然无法在请求后接收值。经过长时间的调试后,我知道以我提供的形式enctype="multipart/form-data"无法获取值。我只是删除了它,它为我工作。


是的,这也可以使表单主体起作用,随后又导致了我的表单的另一个问题-基本上无法按要求上传文件enctype="multipart/form-data"
tsando

顺便说一句,仅添加到我的上述评论中,我设法使其工作了multer-请参阅npmjs.com/package/multer
tsando

3

看来,如果您不使用任何encType(默认值为application/x-www-form-urlencoded),那么您确实会获得文本输入字段,但不会获得文件。

如果您有一个要在其中张贴文本输入和文件的表单,则使用multipart/form-data编码类型,此外还要使用multer中间件。Multer将解析请求对象并req.file为您做准备,所有其他输入字段将通过提供req.body


1
谢谢- multer确实是我的问题的解决方案。如果您可以添加一个示例来说明如何将其用作答案的一部分,
那就太好了

2

我遇到了类似的问题,我只是混合了回调参数的顺序。确保您以正确的顺序设置了回调函数。至少对于有相同问题的任何人。

router.post('/', function(req, res){});

2

确保[“ key”:“ type”,“ value”:“ json”]&[“ key”:“ Content-Type”,“ value”:“ application / x-www-form-urlencoded”]在您的邮递员请求标头


2

multer按照上面的建议解决了这个问题,但是他们错过了给出如何执行此操作的完整示例。基本上,当您使用的表单组时,可能会发生这种情况enctype="multipart/form-data"。这是我使用的表单的HTML:

<form action="/stats" enctype="multipart/form-data" method="post">
  <div class="form-group">
    <input type="file" class="form-control-file" name="uploaded_file">
    <input type="text" class="form-control" placeholder="Number of speakers" name="nspeakers">
    <input type="submit" value="Get me the stats!" class="btn btn-default">            
  </div>
</form>

这里是如何使用multer与获得这种形式的价值和名字Express.jsnode.js

var multer  = require('multer')
var upload = multer({ dest: './public/data/uploads/' })
app.post('/stats', upload.single('uploaded_file'), function (req, res) {
   // req.file is the name of your file in the form above, here 'uploaded_file'
   // req.body will hold the text fields, if there were any 
   console.log(req.file, req.body)
});

1

几分钟前我遇到了同样的问题,我尝试了上述答案中的所有可能方法,但其中任何一个都有效。

我唯一做的就是升级Node JS版本,我不知道升级可能会影响某些事情,但是确实如此。

我已经安装了Node JS版本10.15.0(最新版本),我回到了该版本,8.11.3现在一切正常。也许body-parser模块应该对此进行修复。


1

我的输入中没有名称...我的请求为空...很高兴完成了,我可以继续编码。感谢大家!

答:我使用Jason Kim:

所以代替

<input type="password" class="form-control" id="password">

我有这个

<input type="password" class="form-control" id="password" name="password">

1

JSON.stringify(data)通过AJAX发送邮件时,您不应这样做,如下所示。

这是不正确的代码:

function callAjax(url, data) {
    $.ajax({
        url: url,
        type: "POST",
        data: JSON.stringify(data),
        success: function(d) {
            alert("successs "+ JSON.stringify(d));
        }
    });
}   

正确的代码是:

function callAjax(url, data) {
    $.ajax({
        url: url,
        type: "POST",
        data: data,
        success: function(d) {
            alert("successs "+ JSON.stringify(d));
        }
    });
}

这里要注意的关键是在输入时,请确保大写“ POST”。我见过一些实例,其中仅使用“ post”导致空白的req.body。
Matt C.19年

1

如果您是邮递员,请在请求API时确认这些内容

在此处输入图片说明


0

我使用的是restify而不是express,遇到了同样的问题。解决方案是:

server.use(restify.bodyParser());


0

app.use(bodyParser.urlencoded());将代码更改为

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

在邮递员中,将标头更改Content-Type值从 更改application/x-www-form-urlencodedapplication/json

Ta :-)


0

谢谢大家的精彩回答!花了很多时间寻找解决方案,而在我这边,我犯了一个基本错误:我bodyParser.json()从函数内部调用:

app.use(['/password'], async (req, res, next) => {
  bodyParser.json()
  /.../
  next()
})

我只需要做就可以app.use(['/password'], bodyParser.json())了...


0

在邮递员中,即使遵循了可接受的答案,我也得到了一个空的请求正文。原来,该问题未传递名为

Content-Length : <calculated when request is sent>

默认情况下(与其他5个一起)存在此标头,但我已将其禁用。启用它,您将收到请求正文。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.