如何在 Node.js 中处理 POST 数据?

How to process POST data in Node.js?

提问人:Ming-Tang 提问时间:11/28/2010 最后编辑:nabsterMing-Tang 更新时间:11/2/2022 访问量:1276842

问:

如何在 Node.js 中提取从 HTTP 方法发送的表单数据 () 和文件上传?form[method="post"]POST

我阅读了文档,用谷歌搜索了一下,但一无所获。

function (request, response) {
    //request.post????
}

有图书馆或黑客吗?

节点.js http-post

评论

2赞 Andrea Giammarchi 5/22/2022
很难相信没有人在此页面中提到 URLSearchParams,这是解析接收到的正文的标准方法,以及 Node.js 本身的建议,因为模块被认为是遗留的并且没有维护querystring
1赞 Ollie Williams 6/9/2022
这对文件上传有什么帮助?@AndreaGiammarchi

答:

666赞 Baggz 11/28/2010 #1

如果您使用 Express(Node.js 的高性能、高级 Web 开发),您可以执行以下操作:

HTML格式:

<form method="post" action="/">
    <input type="text" name="user[name]">
    <input type="text" name="user[email]">
    <input type="submit" value="Submit">
</form>

API 客户端:

fetch('/', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json'
    },
    body: JSON.stringify({
        user: {
            name: "John",
            email: "[email protected]"
        }
    })
});

Node.js:(从 Express v4.16.0 开始)

// Parse URL-encoded bodies (as sent by HTML forms)
app.use(express.urlencoded());

// Parse JSON bodies (as sent by API clients)
app.use(express.json());

// Access the parse results as request.body
app.post('/', function(request, response){
    console.log(request.body.user.name);
    console.log(request.body.user.email);
});

Node.js:(适用于 Express <4.16.0)

const bodyParser = require("body-parser");

/** bodyParser.urlencoded(options)
 * Parses the text as URL encoded data (which is how browsers tend to send form data from regular forms set to POST)
 * and exposes the resulting object (containing the keys and values) on req.body
 */
app.use(bodyParser.urlencoded({
    extended: true
}));

/**bodyParser.json(options)
 * Parses the text as JSON and exposes the resulting object on req.body.
 */
app.use(bodyParser.json());

app.post("/", function (req, res) {
    console.log(req.body.user.name)
});

评论

50赞 Julian Birch 6/20/2011
如果要使用较低级别的入口点,该功能实际上位于 connect 的 BodyParser 模块中。
16赞 sbose 4/16/2012
我很困惑。name=“user[email]” 如何对应 request.body.email ?
46赞 Samuel Katz 7/19/2012
神!!我生气了,必须同时阅读同一框架的 3 个 doumentations :/nodejs.org/api/http.htmlsenchalabs.org/connect & expressjs.com/guide.html
18赞 pettys 5/10/2013
直到我添加.app.use(express.bodyParser());
35赞 Shawn Whinnery 10/16/2014
Express 之于节点,就像 jQuery 之于客户端 JS 一样。每次我在谷歌上搜索节点的帮助时,我都会得到这些蹩脚的“使用快递!”的答案。解析帖子数据真的如此困难,以至于有理由安装整个 Web 框架吗?
765赞 Casey Chu 11/30/2010 #2

您可以使用查询字符串模块:

var qs = require('querystring');

function (request, response) {
    if (request.method == 'POST') {
        var body = '';

        request.on('data', function (data) {
            body += data;

            // Too much POST data, kill the connection!
            // 1e6 === 1 * Math.pow(10, 6) === 1 * 1000000 ~~~ 1MB
            if (body.length > 1e6)
                request.connection.destroy();
        });

        request.on('end', function () {
            var post = qs.parse(body);
            // use post['blah'], etc.
        });
    }
}

现在,例如,如果您有一个带有 name 的字段,则可以使用变量访问它:inputagepost

console.log(post.age);

评论

9赞 Casey Chu 12/27/2011
@thejh嗯,这是一个很好的观点。不过,添加这一点应该不难,因此为了简单起见,我将把它排除在示例之外。
92赞 Juan Lanus 4/2/2013
Node.js Web 服务器开发受到中间件的困扰,需要您研究它们数小时,以节省几分钟的编码时间。更不用说几乎所有它们提供的文档了。你的申请最终依赖于其他人的标准,而不是你的标准。以及任意数量的性能问题。
5赞 Michael Moeller 5/8/2013
var POST = qs.parse(body); // use POST仅适用于像我这样的菜鸟:当输入文本字段的名称为“用户”时,将显示该字段的数据。例如Post.userconsole.log(Post.user);
7赞 Thomas Fankhauser 6/26/2013
您还可以使用回调,而不是将数据构建到正文字符串中。一旦发射,身体就可以通过readablerequest.read();
5赞 collimarco 10/28/2014
请注意,这不会阻止回调的执行!例如,“on end”回调将与截断的正文一起执行!这可能不是你想要的......req.connection.destroy();
2赞 Pavel Koryagin 9/16/2011 #3

如果你不想像 Express 那样使用整个框架,但你还需要不同类型的表单,包括上传,那么福尔马林可能是一个不错的选择。

它列在 Node.js 模块

163赞 thejh 12/27/2011 #4

如果有人试图淹没您的RAM,请确保终止连接!

var qs = require('querystring');

function (request, response) {
    if (request.method == 'POST') {
        var body = '';
        request.on('data', function (data) {
            body += data;
            // 1e6 === 1 * Math.pow(10, 6) === 1 * 1000000 ~~~ 1MB
            if (body.length > 1e6) { 
                // FLOOD ATTACK OR FAULTY CLIENT, NUKE REQUEST
                request.connection.destroy();
            }
        });
        request.on('end', function () {

            var POST = qs.parse(body);
            // use POST

        });
    }
}

评论

59赞 neoascetic 7/23/2012
您还可能返回 HTTP 413 错误代码(请求实体太大)
2赞 thejh 4/6/2013
@SSHThis:不,是 1*10^6=1000000。
1赞 thejh 4/25/2013
@tq:在本例中为 POST[name](例如 POST[“foo”])。
3赞 Michael Moeller 5/8/2013
var POST = qs.parse(body); // use POST仅适用于菜鸟:当输入文本字段的名称为“user”时,Post.user 将显示该字段的数据。例如,console.log(Post.user);
3赞 Matt Canty 5/10/2013
有人可以帮忙吗,如果我发布 {'Name':'Joe'},我会在 qs 之后得到 { {'Name':'Joe'} : '' }。解析(POST)...
108赞 Mahn 8/19/2012 #5

这是一个非常简单的无框架包装器,基于此处发布的其他答案和文章:

var http = require('http');
var querystring = require('querystring');

function processPost(request, response, callback) {
    var queryData = "";
    if(typeof callback !== 'function') return null;

    if(request.method == 'POST') {
        request.on('data', function(data) {
            queryData += data;
            if(queryData.length > 1e6) {
                queryData = "";
                response.writeHead(413, {'Content-Type': 'text/plain'}).end();
                request.connection.destroy();
            }
        });

        request.on('end', function() {
            request.post = querystring.parse(queryData);
            callback();
        });

    } else {
        response.writeHead(405, {'Content-Type': 'text/plain'});
        response.end();
    }
}

使用示例:

http.createServer(function(request, response) {
    if(request.method == 'POST') {
        processPost(request, response, function() {
            console.log(request.post);
            // Use request.post here

            response.writeHead(200, "OK", {'Content-Type': 'text/plain'});
            response.end();
        });
    } else {
        response.writeHead(200, "OK", {'Content-Type': 'text/plain'});
        response.end();
    }

}).listen(8000);

评论

1赞 Pavel Nikolov 2/23/2013
难道不应该将此检查移动到单独的中间件中,以便它可以检查所有 post/put 请求的请求是否过大
1赞 Mahn 2/23/2013
@PavelNikolov这主要是为了快速和肮脏的工作,否则最好像这里公认的答案建议的那样使用 Express(它可能也负责管理大型请求)。不过,您可以根据自己的喜好随意修改和“分叉”它。
0赞 B T 7/13/2013
.read() 方法呢?http 模块不支持吗?例如。response.read()
0赞 Jotham 4/3/2014
嘿,只是好奇 - 为什么您将有效负载放入响应对象 (response.post) 而不是请求对象中?
0赞 Mahn 4/3/2014
@Jotham好问题...我不知道为什么我没有早点注意到这一点,但没有理由它应该是而不是更合乎逻辑的.我更新了帖子。response.postrequest.post
5赞 Thomas Fankhauser 6/26/2013 #6

如果您不想将数据与回调一起分块,则始终可以像这样使用回调:datareadable

// Read Body when Available
request.on("readable", function(){
  request.body = '';
  while (null !== (request.body += request.read())){}
});

// Do something with it
request.on("end", function(){
  request.body //-> POST Parameters as String
});

这种方法会修改传入的请求,但一旦完成响应,请求就会被垃圾回收,所以这应该不是问题。

如果您害怕巨大的身体,一种先进的方法是先检查体型。

评论

0赞 doug65536 12/11/2013
方便的方法,但是您如何以一种不会被恶意请求愚弄的方式“先检查体型”呢?
0赞 Thomas Fankhauser 12/11/2013
request是一个普通的 node.js 流,因此您可以检查正文长度并在必要时中止请求。request.headers
1赞 Farid Nouri Neshat 8/11/2017
@ThomasFankhauser 标头中的正文长度可能不正确,甚至不存在。正确的方法是,当身体到达并且您正在缓冲它时,您检查尺寸以确保它不会超过限制。
3赞 PatricioS 8/11/2013 #7

如果您使用的是 Express.js,则必须先添加中间件 bodyParser,然后才能访问 req.body:

app.use(express.bodyParser());

然后你可以要求

req.body.user

评论

0赞 Collierton 2/26/2016
大多数中间件(如 bodyParser)不再与 Express 捆绑在一起,必须单独安装。请参阅上面@nikodean2的答案以获取更新的答案
0赞 Chris Allinson 11/20/2016
app.use(bodyParser());有效但给我弃用红色错误消息
10赞 Dmitry Efimenko 5/21/2014 #8

如果您使用 node-formidable,您可以这样做:

var formidable = require("formidable");

var form = new formidable.IncomingForm();
form.parse(request, function (err, fields) {
    console.log(fields.parameter1);
    console.log(fields.parameter2);
    // ...
});

评论

0赞 Lion789 3/12/2016
我的路径有问题,当我尝试使用路径或路径 + 名称通过 lwip.open(path 或 path + name 访问文件时,我收到错误作为未获取的图像。
97赞 Lewis 7/22/2014 #9

如果将数据编码为 JSON,然后将其发送到 Node.js,则会更干净。

function (req, res) {
    if (req.method == 'POST') {
        var jsonString = '';

        req.on('data', function (data) {
            jsonString += data;
        });

        req.on('end', function () {
            console.log(JSON.parse(jsonString));
        });
    }
}

评论

2赞 wmassingham 3/20/2015
这就是对我有用的东西。事实证明,其他解决方案返回了一个看起来像 JSON 但未解析的字符串。而不是,把身体变成了可用的东西。示例: ,然后使用 .(故事的寓意,如果你对你所看到的感到困惑,不要忘记!qs.parse()JSON.parse()var post = JSON.parse(body);post.fieldnametypeof
16赞 ecarrizo 9/14/2015
好吧,请注意,您必须尝试捕获 JSON.parse 函数,因为如果我想使您的应用程序崩溃,只需发送带有原始文本的正文即可。
0赞 Farid Nouri Neshat 11/20/2017
您应该使用它来使其正常工作,否则它可能无法正确处理非 ascii 字符。request.setEncoding
0赞 Saeedeh 6/22/2020
这真的很有帮助
21赞 sourcecode 10/10/2014 #10

您可以使用 Node.js 体解析中间件。body-parser

首次加载body-parser

$ npm install body-parser --save

一些示例代码

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

var app = express()

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


app.use(function (req, res) {
  var post_data = req.body;
  console.log(post_data);
})

更多文档可以在这里找到

评论

1赞 Philip Enc 6/8/2021
我只是复制/粘贴了这个解决方案,req.body是空的。也许较旧的 express 版本有效,但现在不行了......
40赞 Shawn Whinnery 10/16/2014 #11

对于任何想知道如何在不安装 Web 框架的情况下完成这项微不足道的任务的人,我设法将其放在一起。几乎没有生产就绪,但它似乎有效。

function handler(req, res) {
    var POST = {};
    if (req.method == 'POST') {
        req.on('data', function(data) {
            data = data.toString();
            data = data.split('&');
            for (var i = 0; i < data.length; i++) {
                var _data = data[i].split("=");
                POST[_data[0]] = _data[1];
            }
            console.log(POST);
        })
    }
}

评论

0赞 luis-br 5/19/2017
终于为这个奇怪的问题提供了一个完整的工作解决方案..此外,前面的答案对理解为什么回调开始时请求中没有任何数据有很大帮助。非常感谢!
4赞 Konstantin 6/17/2017
1) 此答案假设数据是字符串。在一般情况下,假设不好。2) 这个答案假设数据在一个块中到达。否则,按“=”拆分将产生不可预知的结果。在一般情况下,假设不好。
0赞 Shawn Whinnery 7/12/2017
@Konstantin 实际上,这个答案假设数据是一个缓冲区。看看这个。stackoverflow.com/questions/14551194/......还有这个。millermedeiros.github.io/mdoc/examples/node_api/doc/......
1赞 Maneesh Singh 1/19/2015 #12

您可以在不使用 Express 的情况下提取 POST 参数。

1:nmp install multiparty

2:导入多方。如var multiparty = require('multiparty');

3: '

if(req.method ==='POST'){
   var form = new multiparty.Form();
   form.parse(req, function(err, fields, files) {
      console.log(fields['userfile1'][0]);
    });
    }

4:HTML 表单是 .

<form method=POST enctype=multipart/form-data>
<input type=text name=userfile1><br>
<input type=submit>
</form>

我希望这对你有用。谢谢。

0赞 acanimal 7/14/2015 #13

限制 POST 大小,避免淹没您的节点应用程序。 有一个很棒的原始体模块,适用于快递和连接,可以帮助您按大小和长度限制请求。

1赞 user203687 8/7/2015 #14

我找到了一个视频,解释了如何实现这一目标:https://www.youtube.com/watch?v=nuw48-u3Yrg

它使用默认的“http”模块以及“querystring”和“stringbuilder”模块。应用程序从网页中获取两个数字(使用两个文本框),并在提交时返回这两个数字的总和(以及将值保留在文本框中)。这是我在其他任何地方都能找到的最好的例子。

相关源码:

var http = require("http");
var qs = require("querystring");
var StringBuilder = require("stringbuilder");

var port = 9000;

function getCalcHtml(req, resp, data) {
    var sb = new StringBuilder({ newline: "\r\n" });
    sb.appendLine("<html>");
    sb.appendLine(" <body>");
    sb.appendLine("     <form method='post'>");
    sb.appendLine("         <table>");
    sb.appendLine("             <tr>");
    sb.appendLine("                 <td>Enter First No: </td>");

    if (data && data.txtFirstNo) {
        sb.appendLine("                 <td><input type='text' id='txtFirstNo' name='txtFirstNo' value='{0}'/></td>", data.txtFirstNo);
    }
    else {
        sb.appendLine("                 <td><input type='text' id='txtFirstNo' name='txtFirstNo' /></td>");
    }

    sb.appendLine("             </tr>");
    sb.appendLine("             <tr>");
    sb.appendLine("                 <td>Enter Second No: </td>");

    if (data && data.txtSecondNo) {
        sb.appendLine("                 <td><input type='text' id='txtSecondNo' name='txtSecondNo' value='{0}'/></td>", data.txtSecondNo);
    }
    else {
        sb.appendLine("                 <td><input type='text' id='txtSecondNo' name='txtSecondNo' /></td>");
    }

    sb.appendLine("             </tr>");
    sb.appendLine("             <tr>");
    sb.appendLine("                 <td><input type='submit' value='Calculate' /></td>");
    sb.appendLine("             </tr>");

    if (data && data.txtFirstNo && data.txtSecondNo) {
        var sum = parseInt(data.txtFirstNo) + parseInt(data.txtSecondNo);
        sb.appendLine("             <tr>");
        sb.appendLine("                 <td>Sum: {0}</td>", sum);
        sb.appendLine("             </tr>");
    }

    sb.appendLine("         </table>");
    sb.appendLine("     </form>")
    sb.appendLine(" </body>");
    sb.appendLine("</html>");
    sb.build(function (err, result) {
        resp.write(result);
        resp.end();
    });
}

function getCalcForm(req, resp, data) {
    resp.writeHead(200, { "Content-Type": "text/html" });
    getCalcHtml(req, resp, data);
}

function getHome(req, resp) {
    resp.writeHead(200, { "Content-Type": "text/html" });
    resp.write("<html><html><head><title>Home</title></head><body>Want to some calculation? Click <a href='/calc'>here</a></body></html>");
    resp.end();
}

function get404(req, resp) {
    resp.writeHead(404, "Resource Not Found", { "Content-Type": "text/html" });
    resp.write("<html><html><head><title>404</title></head><body>404: Resource not found. Go to <a href='/'>Home</a></body></html>");
    resp.end();
}

function get405(req, resp) {
    resp.writeHead(405, "Method not supported", { "Content-Type": "text/html" });
    resp.write("<html><html><head><title>405</title></head><body>405: Method not supported</body></html>");
    resp.end();
}

http.createServer(function (req, resp) {
    switch (req.method) {
        case "GET":
            if (req.url === "/") {
                getHome(req, resp);
            }
            else if (req.url === "/calc") {
                getCalcForm(req, resp);
            }
            else {
                get404(req, resp);
            }
            break;
        case "POST":
            if (req.url === "/calc") {
                var reqBody = '';
                req.on('data', function (data) {
                    reqBody += data;
                    if (reqBody.length > 1e7) { //10MB
                        resp.writeHead(413, 'Request Entity Too Large', { 'Content-Type': 'text/html' });
                        resp.end('<!doctype html><html><head><title>413</title></head><body>413: Request Entity Too Large</body></html>');
                    }
                });
                req.on('end', function () {
                    var formData = qs.parse(reqBody);
                    getCalcForm(req, resp, formData);
                });
            }
            else {
                get404(req, resp);
            }
            break;
        default:
            get405(req, resp);
            break;
    }
}).listen(port);
0赞 user3526 8/13/2015 #15

如果它涉及文件上传,浏览器通常会将其作为内容类型发送。 在这种情况下,您可以使用它"multipart/form-data"

var multipart = require('multipart');
multipart.parse(req)

参考文献 1

参考文献 2

4赞 nikodean2 11/4/2015 #16

有多种方法可以做到这一点。但是,我知道的最快方法是将 Express.js 库与正文解析器一起使用。

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

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

app.post("/pathpostdataissentto", function(request, response) {
  console.log(request.body);
  //Or
  console.log(request.body.fieldName);
});

app.listen(8080);

这适用于字符串,但如果 POST 数据包含 JSON 数组,我会将 bodyParser.urlencoded 更改为 bodyParser.json。

更多的信息: http://www.kompulsa.com/how-to-accept-and-parse-post-requests-in-node-js/

1赞 Geza Turi 5/11/2016 #17

在这样的表单域上

   <input type="text" name="user[name]" value="MyName">
   <input type="text" name="user[email]" value="[email protected]">

上面的一些答案会失败,因为它们只支持平面数据。

现在,我使用的是 Casey Chu 答案,但使用“qs”而不是“querystring”模块。这也是“body-parser”使用的模块。因此,如果您想要嵌套数据,则必须安装 qs。

npm install qs --save

然后替换第一行,如下所示:

//var qs = require('querystring');
var qs = require('qs'); 

function (request, response) {
    if (request.method == 'POST') {
        var body = '';

        request.on('data', function (data) {
            body += data;

            // Too much POST data, kill the connection!
            // 1e6 === 1 * Math.pow(10, 6) === 1 * 1000000 ~~~ 1MB
            if (body.length > 1e6)
                request.connection.destroy();
        });

        request.on('end', function () {
            var post = qs.parse(body);
            console.log(post.user.name); // should work
            // use post['blah'], etc.
        });
    }
}
2赞 lukyer 6/8/2016 #18

对于那些使用原始二进制 POST 上传而不产生编码开销的用户,您可以使用:

客户:

var xhr = new XMLHttpRequest();
xhr.open("POST", "/api/upload", true);
var blob = new Uint8Array([65,72,79,74]); // or e.g. recorder.getBlob()
xhr.send(blob);

服务器:

var express = require('express');
var router = express.Router();
var fs = require('fs');

router.use (function(req, res, next) {
  var data='';
  req.setEncoding('binary');
  req.on('data', function(chunk) {
    data += chunk;
  });

  req.on('end', function() {
    req.body = data;
    next();
  });
});

router.post('/api/upload', function(req, res, next) {
  fs.writeFile("binaryFile.png", req.body, 'binary', function(err) {
    res.send("Binary POST successful!");
  });
});
5赞 Zaz 7/17/2016 #19

您需要使用POSTrequest.on('data', function(chunk) {...})

const http = require('http');

http.createServer((req, res) => {
    if (req.method == 'POST') {
        whole = ''
        req.on('data', (chunk) => {
            # consider adding size limit here
            whole += chunk.toString()
        })

        req.on('end', () => {
            console.log(whole)
            res.writeHead(200, 'OK', {'Content-Type': 'text/html'})
            res.end('Data received.')
        })
    }
}).listen(8080)

您应该考虑按照 jh 的建议在指定位置添加大小限制。

评论

0赞 6/8/2017
这是否更容易受到慢懒猴的攻击?
0赞 Gershom Maes 9/26/2017
Nodejs 比 php 更不容易受到 slow-loris 的影响,因为它不会围绕每个 http 连接构建一个大型会话对象。但是,此代码似乎仍可能引入慢速懒惰漏洞。如果在该窗口内未收到完整的请求,则可以通过在一段时间后结束连接来防止这种情况。setTimeout
227赞 Farid Nouri Neshat 1/7/2017 #20

这里的很多答案不再是好的做法,或者没有解释任何事情,所以这就是我写这篇文章的原因。

基本

当调用 http.createServer 的回调时,就是服务器实际已经收到了请求的所有头,但有可能数据还没有收到,所以我们不得不等待。http 请求对象(一个 http.IncomingMessage instance) 实际上是一个可读的流。在可读流中,每当一个数据块到达时,都会发出一个数据事件(假设你已经注册了一个回调),当所有数据块都到达时,就会发出一个结束事件。下面是一个关于如何侦听事件的示例:

http.createServer((request, response) => {
  console.log('Now we have a http message with headers but no data yet.');
  request.on('data', chunk => {
    console.log('A chunk of data has arrived: ', chunk);
  });
  request.on('end', () => {
    console.log('No more data');
  })
}).listen(8080)

将缓冲区转换为字符串

如果你尝试这样做,你会注意到块是缓冲区。如果您不处理二进制数据,而是需要使用字符串,我建议使用 request.setEncoding 方法,该方法会导致流发出使用给定编码解释的字符串并正确处理多字节字符。

缓冲块

现在你可能对每个块本身不感兴趣,所以在这种情况下,你可能想像这样缓冲它:

http.createServer((request, response) => {
  const chunks = [];
  request.on('data', chunk => chunks.push(chunk));
  request.on('end', () => {
    const data = Buffer.concat(chunks);
    console.log('Data: ', data);
  })
}).listen(8080)

这里使用 Buffer.concat,它只是连接所有缓冲区并返回一个大缓冲区。您还可以使用 concat-stream 模块,它执行相同的操作:

const http = require('http');
const concat = require('concat-stream');
http.createServer((request, response) => {
  concat(request, data => {
    console.log('Data: ', data);
  });
}).listen(8080)

解析内容

如果您尝试接受没有文件的 HTML 表单 POST 提交,或者使用默认内容类型处理 jQuery ajax 调用,则内容类型为编码。可以使用查询字符串模块对其进行反序列化并访问属性:application/x-www-form-urlencodedutf-8

const http = require('http');
const concat = require('concat-stream');
const qs = require('querystring');
http.createServer((request, response) => {
  concat(request, buffer => {
    const data = qs.parse(buffer.toString());
    console.log('Data: ', data);
  });
}).listen(8080)

如果内容类型是 JSON,则只需使用 JSON.parse 而不是 qs.parse

如果您正在处理文件或处理多部分内容类型,那么在这种情况下,您应该使用类似 formidable 的东西,它可以消除处理它的所有痛苦。看看我的另一个答案,我在其中发布了多部分内容的有用链接和模块。

管道

如果您不想解析内容,而是将其传递到其他地方,例如将其作为数据发送到另一个 http 请求或将其保存到文件中,我建议将其管道化而不是缓冲它,因为它会减少代码,更好地处理背压,它会占用更少的内存,在某些情况下更快。

因此,如果要将内容保存到文件中:

 http.createServer((request, response) => {
   request.pipe(fs.createWriteStream('./request'));
 }).listen(8080)

限制数据量

正如其他答案所指出的,请记住,恶意客户端可能会向您发送大量数据以使您的应用程序崩溃或填满您的内存,因此为了保护这一点,请确保您删除发出超过特定限制的数据的请求。如果不使用库来处理传入的数据。我建议使用像stream-meter这样的东西,如果达到指定的限制,它可以中止请求:

limitedStream = request.pipe(meter(1e7));
limitedStream.on('data', ...);
limitedStream.on('end', ...);

request.pipe(meter(1e7)).pipe(createWriteStream(...));

concat(request.pipe(meter(1e7)), ...);

NPM 模块

虽然我在上面描述了如何使用 HTTP 请求正文,但只是为了 缓冲和解析内容,我建议使用这些模块之一而不是自己实现,因为它们可能会更好地处理边缘情况。对于表达,我建议使用 body-parser。对于 koa,有一个类似的模块

如果你不使用框架,body是相当不错的。

评论

1赞 Yan King Yin 3/28/2017
谢谢,我使用了你的代码,我收到了神秘的重复消息。难道是变量被重用并被多次调用吗?我怎样才能避免这种情况?requestrequest.on('end')
1赞 Farid Nouri Neshat 3/28/2017
如果不看你的代码,我就不知道为什么。请注意,对于每个请求,都会被调用。request.on('end', ...)
1赞 Yan King Yin 3/28/2017
这可能与您的代码无关,我正在执行服务器发送的事件,并且可能搞砸了......您的代码工作正常,无论如何都要感谢:)
6赞 montrealist 10/26/2019
这是这个问题的最佳答案。🧐
6赞 webduvet 8/6/2020
这应该被标记为已接受的答案。问题是如何在nodejs中而不是在expressjs中处理表单。
7赞 Er Shubham Patidar 7/19/2017 #21

1) 从 npm 安装。'body-parser'

2)然后在你的app.ts

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

3)然后你需要写

app.use(bodyParser.json())

app.ts 模块中

4) 请记住,您包括

app.use(bodyParser.json())

在任何模块声明的顶部或之前。

前任:

app.use(bodyParser.json())
app.use('/user',user);

5) 然后使用

var postdata = req.body;
12赞 Nadhas 1/24/2018 #22

参考: https://nodejs.org/en/docs/guides/anatomy-of-an-http-transaction/

let body = [];
request.on('data', (chunk) => {
  body.push(chunk);
}).on('end', () => {
  body = Buffer.concat(body).toString();
  // at this point, `body` has the entire request body stored in it as a string
});
10赞 Oleksii Trekhleb 9/20/2018 #23

如果您更喜欢使用纯 Node.js,那么您可以提取 POST 数据,如下所示:

// Dependencies
const StringDecoder = require('string_decoder').StringDecoder;
const http = require('http');

// Instantiate the HTTP server.
const httpServer = http.createServer((request, response) => {
  // Get the payload, if any.
  const decoder = new StringDecoder('utf-8');
  let payload = '';

  request.on('data', (data) => {
    payload += decoder.write(data);
  });

  request.on('end', () => {
    payload += decoder.end();

    // Parse payload to object.
    payload = JSON.parse(payload);

    // Do smoething with the payload....
  });
};

// Start the HTTP server.
const port = 3000;
httpServer.listen(port, () => {
  console.log(`The server is listening on port ${port}`);
});

1赞 Big Money 12/1/2018 #24

您可以使用 express 中间件,它现在内置了 body-parser。这意味着您需要做的就是以下几点:

import express from 'express'

const app = express()

app.use(express.json())

app.post('/thing', (req, res) => {
  console.log(req.body) // <-- this will access the body of the post
  res.sendStatus(200)
})

该代码示例是带有 Express 4.16.x 的 ES6

-1赞 Kaveesha Baddage 1/23/2019 #25

您可以使用“请求 - 简化的 HTTP 客户端”和 Javascript Promise 轻松发送和获取 POST 请求的响应。

var request = require('request');

function getData() {
    var options = {
        url: 'https://example.com',
        headers: {
            'Content-Type': 'application/json'
        }
    };

    return new Promise(function (resolve, reject) {
        var responseData;
        var req = request.post(options, (err, res, body) => {
            if (err) {
                console.log(err);
                reject(err);
            } else {
                console.log("Responce Data", JSON.parse(body));
                responseData = body;
                resolve(responseData);
            }
        });
    });
}
0赞 Rubin bhandari 3/4/2019 #26

如果您希望表单数据在 req.body 中可用,则需要使用 bodyParser()。 body-parser 解析您的请求并将其转换为一种格式,您可以从中轻松提取可能需要的相关信息。

例如,假设您的前端有一个注册表单。您正在填写它,并要求服务器将详细信息保存在某个地方。

如果您使用 body-parser,从请求中提取用户名和密码非常简单,如下所示。

.............................................................

var loginDetails = {

username : request.body.username,

password : request.body.password

};
4赞 antelove 9/24/2019 #27

快递版 v4.17.0

app.use(express.urlencoded( {extended: true} ))

console.log(req.body) // object

演示表格

另一个答案相关

3赞 De Bonheur 4/19/2021 #28

如果您从 POST 接收 JSON 格式的数据。:

  import http from 'http';
  const hostname  = '127.0.0.1'; 
  const port = 3000;

  const httpServer:  http.Server = http.createServer((req: http.IncomingMessage, res: 
         http.ServerResponse) => {

        if(req.method === 'POST') {
        let body: string = ''; 
          req.on('data',(chunck) => {
            body += chunck;
          });

          req.on('end', () => {
            const body = JSON.parse(body);
            res.statusCode = 200;
            res.end('OK post');
          });
       }
 
     });

     httpServer.listen(port, hostname, () => {
       console.info(`Server started at port ${port}`);
     })

评论

2赞 iheathers 10/31/2021
如果有人想知道代码是怎么回事,这里是 nodejs 文档本身的解释。nodejs.org/en/knowledge/HTTP/servers/how-to-read-POST-data
0赞 robm 1/2/2022
这是一种无需快递即可完成的方法
0赞 Peer Reynders 5/22/2022 #29

详细说明使用:URLSearchParams

const http = require('http');

const POST_HTML =
  '<html><head><title>Post Example</title></head>' +
  '<body>' +
  '<form method="post">' +
  'Input 1: <input name="input1"><br>' +
  'Input 2: <input name="input2"><br>' +
  'Input 1: <input name="input1"><br>' +
  '<input type="submit">' +
  '</form>' +
  '</body></html>';

const FORM_DATA = 'application/x-www-form-urlencoded';

function processFormData(body) {
  const params = new URLSearchParams(body);

  for ([name, value] of params.entries()) console.log(`${name}: ${value}`);
}

// req: http.IncomingMessage
// res: http.ServerResponse
//
function requestListener(req, res) {
  const contentType = req.headers['content-type'];
  let body = '';

  const append = (chunk) => {
    body += chunk;
  };
  const complete = () => {
    if (contentType === FORM_DATA) processFormData(body);

    res.writeHead(200);
    res.end(POST_HTML);
  };

  req.on('data', append);
  req.on('end', complete);
}

http.createServer(requestListener).listen(8080);
$ node index.js
input1: one
input2: two
input1: three
6赞 Sergey Pogranichniy 11/2/2022 #30

Node.js 18 以现代异步方式,零依赖:

server.mjs:

import { createServer } from 'node:http';

const rawReqToString = async (req) => {
    const buffers = [];
    for await(const chunk of req){
        buffers.push(chunk);
    }
    return Buffer.concat(buffers).toString();
};

const server = createServer(async (req, res) => {
    const object = JSON.parse(await rawReqToString(req));
    ...
});

server.listen(3000, 'localhost', () => {
    console.log(`The server is running.`);
})