Answers:
如果使用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: "john@example.com"
}
})
});
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)
});
app.use(express.bodyParser());
。
您可以使用以下querystring
模块:
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.
});
}
}
现在,例如,如果您有一个input
名称为name 的字段age
,则可以使用变量来访问它post
:
console.log(post.age);
var POST = qs.parse(body); // use POST
仅适用于像我这样的菜鸟:当输入文本字段的名称为“ user”时,Post.user
将显示该字段的数据。例如console.log(Post.user);
readable
回调,而不是将数据构建到主体字符串中。发射后,尸体可以通过request.read();
req.connection.destroy();
这不会阻止执行回调!例如,“ on end”回调将与截断的正文一起执行!这可能不是您想要的...
如果有人试图淹没您的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
});
}
}
var POST = qs.parse(body); // use POST
仅适用于菜鸟:当输入文本字段的名称为“ user”时,Post.user将显示该字段的数据。例如console.log(Post.user);
这里有很多答案已经不是很好的做法,或者什么也没解释,所以这就是我写这个的原因。
调用http.createServer的回调时,是服务器实际上已接收到该请求的所有标头,但有可能尚未接收到数据,因此我们必须等待。该http请求对象(http.IncomingMessage实例)实际上是一个可读 流。在可读流中,每当有数据块到达时,都会发出一个事件(假设您已经注册了回调),而在所有数据块都到达时,就会发出一个事件。这是有关如何监听事件的示例:data
end
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-urlencoded
具有uft-8
编码。您可以使用querystring模块将其反序列化并访问属性:
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即可。
如果您要处理文件或处理多部分内容类型,则在这种情况下,应使用“可怕”之类的东西来消除所有麻烦。看看我的其他答案,我在其中发布了有用的链接和有关多部分内容的模块。
如果您不想解析内容,而是将其传递到其他地方,例如,将其作为数据发送到另一个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)), ...);
虽然我在上面描述了如何使用HTTP请求正文来简单地缓冲和解析内容,但我建议使用这些模块之一而不是自己实现,因为它们可能会更好地处理边缘情况。为了表达意见,我建议使用body-parser。对于koa,有一个类似的模块。
如果您不使用框架,那么身体会很好。
request
被重新使用并且request.on('end')
被多次调用吗?我该如何避免呢?
request.on('end', ...)
都会被调用。
这是一个非常简单的无框架包装器,它基于此处发布的其他答案和文章:
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);
response.post
而不是更合乎逻辑request.post
。我更新了帖子。
如果将数据编码为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));
});
}
}
qs.parse()
,JSON.parse()
将身体变成可用的东西。示例:var post = JSON.parse(body);
,然后使用访问数据post.fieldname
。(故事的寓意,如果您对所看到的内容感到困惑,请不要忘记typeof
!)
request.setEncoding
来使其正常工作,否则它可能无法正确处理非ASCII字符。
对于想知道如何在不安装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);
})
}
}
您可以使用body-parser
Node.js主体解析中间件。
第一次加载 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);
})
更多文档可以在这里找到
参考: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
});
如果您使用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);
// ...
});
如果您更喜欢使用纯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)'body-parser'
从npm 安装。
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;
如果您不想将数据与data
回调一起分块,则可以始终使用如下readable
回调:
// 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
});
这种方法修改了传入的请求,但是一旦您完成响应,该请求就会被垃圾回收,因此这不会成为问题。
如果您担心庞大的身体,一种高级方法是首先检查身体大小。
request
是正常的node.js流,因此您可以检查request.headers
的正文长度,并在必要时中止请求。
有多种方法可以做到这一点。但是,我知道最快的方法是将Express.js库与body-parser一起使用。
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/
您需要POST
使用以下数据块接收数据request.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)
您应该考虑按照建议的在指定位置添加大小限制。
setTimeout
如果在该时间段内未收到完整请求,则可以通过在一定时间后结束连接来防止这种情况。
如果使用Express.js,则必须先添加中间件bodyParser,然后才能访问req.body:
app.use(express.bodyParser());
那你可以要求
req.body.user
而且,如果您不想使用像Express这样的整个框架,但是还需要其他形式的表单,包括上载,那么福尔马林可能是一个不错的选择。
它在Node.js模块中列出
我找到了一段视频,解释了如何实现此目的: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);
对于那些使用原始二进制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!");
});
});
您可以不使用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 IS。
<form method=POST enctype=multipart/form-data>
<input type=text name=userfile1><br>
<input type=submit>
</form>
希望这对您有用。谢谢。
在此类表单字段上
<input type="text" name="user[name]" value="MyName">
<input type="text" name="user[email]" value="myemail@somewherefarfar.com">
上述某些答案将失败,因为它们仅支持平面数据。
现在,我使用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.
});
}
}
您可以使用“请求-简化的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);
}
});
});
}