【问题标题】:How to process POST data in Node.js?如何在 Node.js 中处理 POST 数据?
【发布时间】:2011-05-16 19:08:16
【问题描述】:

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

我已经阅读了文档,谷歌搜索并没有发现任何东西。

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

有图书馆或黑客吗?

【问题讨论】:

    标签: node.js http-post


    【解决方案1】:

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

    基础知识

    调用http.createServer的回调时,服务器实际上已经收到了请求的所有header,但有可能还没有收到数据,所以我们必须等待它。 http request object(a http.IncomingMessage instance) 实际上是 readable stream。在可读流中,每当数据块到达时,dataevent is emitted(假设您已经注册了一个回调)并且当所有块都到达时,会发出一个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)
    

    将缓冲区转换为字符串

    如果你尝试这个,你会注意到块是buffers。如果您不处理二进制数据而需要使用字符串,我建议使用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 module,它的作用是一样的:

    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 编码。您可以使用querystring module 对其进行反序列化并访问属性:

    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

    如果您正在处理文件或处理多部分内容类型,那么在这种情况下,您应该使用类似强大的东西来消除处理它的所有痛苦。看看我的this other answer,我在其中为多部分内容发布了有用的链接和模块。

    管道

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

    所以如果你想将内容保存到文件中:

     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,有一个 similar module

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

    【讨论】:

    • 谢谢,我使用了你的代码,我收到了神秘的重复消息。会不会是变量request 被重复使用并且request.on('end') 被多次调用?我怎样才能避免这种情况?
    • 如果没有看到您的代码,我不知道为什么。请注意,对于每个请求,都会调用 request.on('end', ...)
    • 这可能与您的代码无关,我正在处理服务器发送的事件并且可能搞砸了...您的代码工作正常,无论如何谢谢:)
    • 这是该问题的最佳答案。 ?
    • 这应该被标记为接受的答案。问题是如何在 nodejs 而不是 expressjs 中处理表单。
    【解决方案2】:

    如果您从 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}`);
         })
    

    【讨论】:

    【解决方案3】:

    Express v4.17.0

    app.use(express.urlencoded( {extended: true} ))
    
    console.log(req.body) // object
    

    Demo Form

    Another Answer Related

    【讨论】:

      【解决方案4】:

      没有中间件的 LINER
      如果您发布以下数据,
      'name':'ABC'
      然后你可以使用下面的一个衬垫来解析它,

      require('url').parse(req.url, true).query.name
      

      【讨论】:

      • OP 询问提取请求正文,这涉及查询参数。
      【解决方案5】:

      如果您使用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

      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)
      });
      

      【讨论】:

      • 功能实际上是在BodyParser模块中的connect,如果你想使用较低级别的入口点。
      • 我很困惑。 name="user[email]" 与 request.body.email 是如何对应的?
      • 天啊!!对于同一个框架,我不得不同时阅读 3 个文档,这让我很生气:/ nodejs.org/api/http.htmlsenchalabs.org/connect & expressjs.com/guide.html
      • 这对我不起作用,直到我添加了app.use(express.bodyParser());
      • Express 之于节点就像 jQuery 之于客户端 JS。每次我谷歌帮助节点时,我都会得到这些蹩脚的“使用快递!”答案。解析发布数据是否真的如此困难,以至于证明安装整个 Web 框架是合理的?
      【解决方案6】:

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

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

      如果你使用 body-parser,从你的请求中提取用户名和密码就像下面这样简单。

      …………………………………………………….

      var loginDetails = {
      
      username : request.body.username,
      
      password : request.body.password
      
      };
      

      【讨论】:

        【解决方案7】:

        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;
        

        【讨论】:

          【解决方案8】:

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

          【讨论】:

            【解决方案9】:

            您可以使用express 中间件,该中间件现在内置了正文解析器。这意味着您只需执行以下操作:

            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

            【讨论】:

              【解决方案10】:

              如果您更喜欢使用纯 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}`);
              });

              【讨论】:

                【解决方案11】:

                参考: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
                });
                

                【讨论】:

                  【解决方案12】:

                  对于任何想知道如何在不安装 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);
                          })
                      }
                  }
                  

                  【讨论】:

                  • 终于为这个奇怪的问题提供了一个完整的解决方案。. 之前的答案也有助于理解为什么回调开始时请求中没有任何数据.. 非常感谢!
                  • 1) 这个答案假设数据是一个字符串。错误的假设,在一般情况下。 2)这个答案假设数据以一个块的形式到达。否则,用 '=' 分割会产生不可预知的结果。错误的假设,在一般情况下。
                  • @Konstantin 实际上这个答案假设数据是一个缓冲区。看一下这个。 stackoverflow.com/questions/14551194/… 还有这个。 millermedeiros.github.io/mdoc/examples/node_api/doc/…
                  【解决方案13】:

                  您需要使用request.on('data', function(chunk) {...}) 分块接收POST 数据

                  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)
                  

                  您应该考虑在thejh suggested 的指示位置添加大小限制。

                  【讨论】:

                  • 这更容易受到慢懒猴攻击吗?
                  • Nodejs 比 php 更不容易受到慢懒猴的影响——因为它不会围绕每个 http 连接构建大型会话对象。然而,这段代码似乎仍然会引入一个慢猴漏洞。如果在该窗口内未收到完整的请求,则可以通过 setTimeout 在一段时间后结束连接来防止这种情况。
                  【解决方案14】:

                  对于那些使用 原始二进制 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!");
                    });
                  });
                  

                  【讨论】:

                    【解决方案15】:

                    像这样的表单域

                       <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.
                            });
                        }
                    }
                    

                    【讨论】:

                      【解决方案16】:

                      如果您将数据编码为 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));
                              });
                          }
                      }
                      

                      【讨论】:

                      • 这对我有用。结果发现其他解决方案返回了一个 看起来 像 JSON 但未被解析的字符串。而不是qs.parse()JSON.parse() 将身体变成了可用的东西。示例:var post = JSON.parse(body);,然后使用post.fieldname 访问数据。 (故事的寓意,如果您对所看到的内容感到困惑,请不要忘记typeof!)
                      • 请注意,您必须尝试捕获 JSON.parse 函数,因为如果我想使您的应用程序崩溃,只需发送带有原始文本的正文即可。
                      • 您应该使用request.setEncoding 使其正常工作,否则它可能无法正确处理非 ascii 字符。
                      • 确实有帮助
                      【解决方案17】:

                      如果你使用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);
                          // ...
                      });
                      

                      【讨论】:

                      • 我的路径有问题,当我尝试使用路径或路径 + 名称通过 lwip.open(path 或路径 + 名称) 访问文件时,我收到一个未获得的错误图片。
                      【解决方案18】:

                      如果你使用Express.js,在访问req.body之前,你必须添加中间件bodyParser:

                      app.use(express.bodyParser());
                      

                      那你可以要求了

                      req.body.user
                      

                      【讨论】:

                      • 大多数中间件(如 bodyParser)不再与 Express 捆绑在一起,必须单独安装。请参阅上面@nikodean2 的答案以获取更多最新答案
                      • app.use(bodyParser());有效,但给了我弃用红色错误消息
                      【解决方案19】:

                      有多种方法可以做到这一点。但是,我知道的最快方法是使用 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/

                      【讨论】:

                        【解决方案20】:

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

                        现在,例如,如果您有一个名为 ageinput 字段,您可以使用变量 post 访问它:

                        console.log(post.age);
                        

                        【讨论】:

                        • @thejh 嗯,这是一个很好的观点。不过,添加它应该不难,所以为了简单起见,我将把它排除在示例之外。
                        • node.js Web 服务器开发受到中间件的困扰,需要您花几个小时研究它们才能节省几分钟的编码时间。更不用说几乎所有的文档都提供了。你的应用程序最终依赖于其他人的标准,而不是你的标准。加上任何数量的性能问题。
                        • var POST = qs.parse(body); // use POST 仅适用于像我这样的菜鸟:当输入文本字段的名称为“用户”时,Post.user 将显示该字段的数据。例如console.log(Post.user);
                        • 您也可以使用readablecallback,而不是将数据构建到正文字符串中。一旦它被触发,身体就可以通过request.read();
                        • 请注意req.connection.destroy(); 不会阻止回调被执行! 例如,“on end”回调将使用截断的主体执行!这可能不是你想要的......
                        【解决方案21】:

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

                        更多文档可以找到here

                        【讨论】:

                        • 我只是复制/粘贴了这个解决方案,req.body 是空的。也许旧的快递版本可以工作,但现在不行了......
                        【解决方案22】:

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

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

                        Reference 1

                        Reference 2

                        【讨论】:

                          【解决方案23】:

                          我找到了一个视频,它解释了如何实现这一点: 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);
                          

                          【讨论】:

                            【解决方案24】:

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

                            【讨论】:

                              【解决方案25】:

                              您可以在不使用 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>
                              

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

                              【讨论】:

                                【解决方案26】:

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

                                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);
                                

                                【讨论】:

                                • 不应该将此检查移动到单独的中间件,以便它可以检查所有 post/put 请求上的请求是否过大
                                • @PavelNikolov 这主要用于快速和肮脏的工作,否则最好使用 Express,就像这里推荐的公认答案一样(这可能也负责管理大型请求)。不过,您可以随意修改和“分叉”它。
                                • .read() 方法呢? http模块不支持吗?例如。 response.read()
                                • 嘿,只是好奇 - 为什么将有效负载放入响应对象 (response.post) 而不是请求对象?
                                • @Jotham 好问题...我不知道为什么我没有早点注意到这一点,但没有理由应该是 response.post 而不是更合乎逻辑的 request.post。我更新了帖子。
                                【解决方案27】:

                                如果您不想将数据与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
                                });
                                

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

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

                                【讨论】:

                                • 方便的方式,但是如何“先检查body size”又不会被恶意请求所蒙骗?
                                • request 是一个普通的 node.js 流,因此您可以检查 request.headers 的主体长度并在必要时中止请求。
                                • @ThomasFankhauser 标头中的正文长度可能不是正确的值,甚至可能不存在。正确的做法是,当身体到达并缓冲它时,检查大小以确保它没有超过限制。
                                【解决方案28】:

                                如果有人试图淹没您的 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
                                
                                        });
                                    }
                                }
                                

                                【讨论】:

                                • 您也可能返回 HTTP 413 错误代码(请求实体太大)
                                • @SSHThis:不,它是 1*10^6=1000000。
                                • @tq:在这种情况下,POST[name](例如 POST["foo"])。
                                • var POST = qs.parse(body); // use POST 仅适用于新手:当输入文本字段的名称为“用户”时,Post.user 将显示该字段的数据。例如console.log(Post.user);
                                • 有人可以帮忙吗,如果我发布 {'Name':'Joe'} 我得到 { {'Name':'Joe'} : '' } after qs.Parse(POST)...
                                【解决方案29】:

                                而如果你不想像Express那样使用整个框架,但又需要不同种类的表单,包括上传,那么formaline可能是个不错的选择。

                                列在Node.js modules

                                【讨论】:

                                  猜你喜欢
                                  • 2013-03-03
                                  • 1970-01-01
                                  • 1970-01-01
                                  • 1970-01-01
                                  • 1970-01-01
                                  • 1970-01-01
                                  • 1970-01-01
                                  • 1970-01-01
                                  相关资源
                                  最近更新 更多