Node.js:如何限制HTTP请求大小和上传文件大小?

35

我正在使用Node.js和express。

我想限制HTTP请求的大小。比如说,如果有人给我发送超过2MB的HTTP请求,我就立刻停止请求。我查看了代码,认为如果我改变核心代码,就可以实现。但是,有没有一种设置max_request_size或类似的方法呢?

这与我的第二个问题有点相关。我正在使用express从req.files获取上传的文件。当文件大小超过一定大小时,有没有一种方法可以停止将文件写入/tmp文件夹(这是默认上传行为)?

7个回答

38

更新一下(2014年7月),由于我不能添加评论:

如上正确指出的那样,新版 Express 已经弃用了 `limit` 中间件,并将其作为 `BodyParser` 中间件的内置选项提供:API

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

   var app = express()
   app.use(bodyParser.json({ limit: '5mb' }))

1
那就是我需要的。谢谢。 - emj365
如何在请求模块中增加限制? - user2678776
2
如果请求的大小不在正文中怎么办? :( 如果有人开始发送50Mb的GET请求会怎样? :( - Fabio Beltramini
1
任何不在正文中的内容都将在头部中,NodeJS设置了最大头部大小的默认限制。例如,在NodeJS版本11.6.0中,限制为8kb。https://nodejs.org/api/http.html#http_http_maxheadersize - James
我该如何在React JS中使用它? - Neeraj Verma
显示剩余2条评论

16

Express使用Connect,它有一个可用的Limit中间件。你可以通过像这样做来在Express应用程序中使用它:

app.use(express.limit('2mb'));

例如,这会将所有HTTP请求限制为2 MB。由于上传的文件是HTTP请求的一部分,任何大于2 MB的文件上传也将被中止。


注意:此中间件已弃用并将很快被移除。有关原因的讨论可在以下网址找到:https://github.com/senchalabs/connect/pull/925#issuecomment-26990726


1
如果我限制为2MB,并发送了1GB的HTTP请求。如果超过2MB,它会立即停止吗?还是返回错误但仍然获取剩余的0.998GB数据? - murvinlai
5
如果我理解正确,源代码可在https://github.com/senchalabs/connect/blob/master/lib/middleware/limit.js获得。该代码会读取分块数据,并一旦超过大小限制就终止请求。 - Rohan Singh
express.limit在Node.js 6中已被废弃作为中间件。 - user1709076

16

GitHub上节点的源代码:

/* Maximium header size allowed. If the macro is not defined
 * before including this header then the default is used. To
 * change the maximum header size, define the macro in the build
 * environment (e.g. -DHTTP_MAX_HEADER_SIZE=<value>). To remove
 * the effective limit on the size of the header, define the macro
 * to a very large number (e.g. -DHTTP_MAX_HEADER_SIZE=0x7fffffff)
 */
#ifndef HTTP_MAX_HEADER_SIZE
# define HTTP_MAX_HEADER_SIZE (80*1024)
#endif 

所以,您需要从源代码重新构建节点以超越80*1024的限制。

您可以在Express 4中使用它来限制请求正文大小/上传文件大小,而不是使用express.json()和express.urlencoded()。 您必须要求body-parser模块并使用其json()和urlencoded()方法,如果未明确为bodyParser.urlencoded()定义扩展选项,则会引发警告(body-parser已弃用undefined extended:provide extended option)。

var bodyParser = require('body-parser');
app.use(bodyParser.json({limit: '50mb'}));
app.use(bodyParser.urlencoded({limit: '50mb', extended: true}));

问题#1(以及我的悬赏重点)是关于请求大小的。但是您的答案是关于请求正文大小的。在bodyParser文档中明确提到,limit参数“控制最大请求正文大小”。 - Fabio Beltramini
Node的Github源代码:/* 允许的最大头部大小。如果在包含此头文件之前未定义该宏,则使用默认值。要更改最大标题大小,请在构建环境中定义该宏(例如,-DHTTP_MAX_HEADER_SIZE=<value>)。要删除标题大小的有效限制,请将该宏定义为非常大的数字(例如,-DHTTP_MAX_HEADER_SIZE=0x7fffffff)*/ #ifndef HTTP_MAX_HEADER_SIZE

define HTTP_MAX_HEADER_SIZE (80*1024)

#endif因此,您需要从源代码重新构建Node以超过80 * 1024的限制。
- AJS

6

如果您需要一个不过时的更新解决方案,可以在app.js文件中添加limit参数实现:

app.use(express.json({limit: '2mb'}));
app.use(express.urlencoded({limit: '2mb', extended: false}));

你也可以这样做:
app.use(express.json({limit: 2000000}));
app.use(express.urlencoded({limit: 2000000, extended: false}));

1
var methodOverride = require('method-override');
app.use(bodyParser.urlencoded({
        extended: true, limit: '50mb'
    }));
app.use(bodyParser.json({limit: '50mb'}));
app.use(methodOverride());

0

问题1的答案:

为了限制HTTP请求大小和上传文件大小,我们需要设置body-parser的限制。

app.use(bodyParser.urlencoded({limit: '50mb',extended: true}));
app.use(bodyParser.json({limit: '50mb'}));

bodyParser.urlencoded

前端传来的文件以urlencoded格式的主体形式出现。

返回仅解析urlencoded主体的中间件。此解析器仅接受主体的UTF-8编码,并支持gzip和deflate编码的自动膨胀。

在中间件之后,请求对象上填充了包含解析数据的新主体对象(即req.body)。该对象将包含键值对,其中值可以是字符串或数组(当extended为false时),也可以是任何类型(当extended为true时)。

bodyParser.json

返回仅解析json的中间件。该解析器接受任何请求正文的Unicode编码,并支持gzip和deflate编码的自动膨胀。
在中间件之后,请求对象上填充包含解析数据的新正文对象(即req.body)。
注意:默认情况下,body parser的输入限制为100kb
问题2的答案:
要更改默认的上传目录,可以使用以下内容。
app.set('uploadDir', './files');  // Sets the upload Directory to files folder in your project.

其他的实现方式

在将bodyParser包含到应用程序中时,我们可以指定上传目录。

app.use(express.bodyParser({uploadDir:'./files', keepExtensions: true}));

参考资料:

问题: https://github.com/expressjs/express/issues/1684

希望这有所帮助!


1
问题#1(以及我的悬赏重点)是关于请求大小的。但是您的答案是关于请求正文大小的。您提供的参考链接中明确提到:“控制最大请求正文大小。” - Fabio Beltramini

0
使用 raw-body。大多数中间件(如 limit)不再与 Express 捆绑在一起,必须单独安装。这是一个示例。
var getRawBody = require('raw-body')
app.use(function (req, res, next) {
      getRawBody(
        stream = req,
        options = {
          length: req.headers['content-length'],
          limit: '100mb',
        },
        callback = function (err, reslt) {
          if (err) {
            return next(err)
          }
          next();
          console.log(req)
        })
    })
  • 记得在app.use之后添加路由器

Express不再允许您使用传统的捆绑中间件明确设置限制,如下所示。

app.use(express.limit('4M'));

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