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

756

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

我已经阅读了文档,进行了谷歌搜索,但没有发现相关信息。

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

有没有库或技巧可用?


2
很难相信在这个页面中没有人提到URLSearchParams,它是解析接收到的主体的标准方式,也是Node.js自身的建议,因为querystring模块被认为是遗留的且未维护 - Andrea Giammarchi
1
那如何有助于文件上传?@AndreaGiammarchi - Ollie Williams
30个回答

2

如果您使用原始二进制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!");
  });
});

1

你可以在不使用express的情况下提取post参数。

1: npm install multiparty

2: 导入multiparty。例如: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>

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


1
在这样的表单字段上
   <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.
        });
    }
}

1
我找到了一个视频,讲解如何实现这个功能: 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);

1
您可以使用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)
})

那个代码示例使用的是ES6和Express 4.16.x。


0

限制POST大小以避免淹没您的节点应用程序。 有一个很棒的raw-body模块,适用于express和connect,可以帮助您通过大小和长度限制请求。


0

关于如何使用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

0

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

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

参考资料 1

参考资料 2


0
如果您希望表单数据在req.body中可用,您需要使用bodyParser()。 body-parser解析您的请求并将其转换为可以轻松提取所需相关信息的格式。
例如,假设您的前端有一个注册表单。 您正在填写它,并要求服务器将详细信息保存在某个地方。
如果您使用body-parser,从您的请求中提取用户名和密码就像以下简单的步骤一样。

……………………………………………………。

var loginDetails = {

username : request.body.username,

password : request.body.password

};

-1

您可以使用“Request - 简化的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);
            }
        });
    });
}

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