Nodejs + express 如何拒绝大文件上传

Nodejs + express 如何拒绝大文件上传

我想在post header到达之后, 文件开始上传之前或者刚开始上传时拒绝post请求 目前使用的方式是在加载bodyparse时设置 app.use(express.bodyParser({ limit: 1000000 //1m })); 这样一来浏览器确实收到一个413,而且后台也没有临时文件出现, 但是浏览器依然在上传文件, 我不知道后台有没有在继续处理这个请求, 如果有的话应该也是占用了不少资源和带宽, 如何能彻底的把文件大上传拒绝掉呢?

12 回复

当然可以。您希望在文件上传过程中尽早拒绝大文件的上传请求。为此,您可以使用中间件来检查文件大小并在达到限制时立即返回错误响应。以下是一个具体的实现方案:

示例代码

首先,安装必要的依赖包(如果尚未安装):

npm install express multer

接下来,创建一个自定义中间件来处理文件大小限制:

const express = require('express');
const multer = require('multer');
const app = express();

// 设置文件大小限制
const fileSizeLimit = 1 * 1024 * 1024; // 1MB

// 创建 Multer 实例并设置存储策略
const upload = multer({
  limits: { fileSize: fileSizeLimit },
  fileFilter(req, file, cb) {
    if (file.size > fileSizeLimit) {
      return cb(new Error('File size exceeds the limit'));
    }
    cb(null, true);
  }
});

// 自定义中间件用于检查文件大小
function checkFileSize(req, res, next) {
  if (req.file && req.file.size > fileSizeLimit) {
    return res.status(413).send({ message: 'File size exceeds the limit' });
  }
  next();
}

// 使用 Multer 和自定义中间件
app.post('/upload', upload.single('file'), checkFileSize, (req, res) => {
  res.send({ message: 'File uploaded successfully' });
});

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

解释

  1. Multer 配置:

    • limits: { fileSize: fileSizeLimit } 设置了文件大小的最大限制。
    • fileFilter 方法在文件过滤时检查文件大小是否超过限制,并在超限时返回错误。
  2. 自定义中间件 checkFileSize:

    • 在文件上传完成后检查文件大小是否超过限制。
    • 如果文件大小超过限制,则返回 413 响应(请求实体过大)。
  3. 路由处理:

    • app.post('/upload', upload.single('file'), checkFileSize, ...) 定义了一个 POST 路由 /upload,用于接收单个文件。
    • upload.single('file') 处理单个文件的上传。
    • checkFileSize 中间件用于检查文件大小。
    • 最终成功上传后返回成功的响应。

这样设置后,当文件大小超过限制时,服务器会在文件完全上传之前返回错误响应,从而避免占用过多的资源和带宽。


传统的express上传文件是,post header发生完毕,然后添加到服务器的临时目录后,在根据size()方法判断是否过大,如果过大就返回413。 而在express.bodyParser( { limit: 3242 } ) 设置最大限制也的确发送了header 头之后,当文件过大也不会拷贝到临时目录 你说的这种,应该后台在处理,否则怎么运用limit属性判断文件是否过大呢

header 中的 Content-Length

在文件上传了1m以后发现依然没有传完就立即断开请求, 这也是一种策略. 无论使用什么策略, 我现在只是不知道完全取消中断请求的方法而已

function OnError(status) {
  var xhr = this;
  if (status === 413) {
    xhr.abort();
  }
}

额,用流的形式读取,把req当做流对象,请求体当做读取的流数据,我试下,不知道可以不

现在我发现我在正文中说的方法不稳定, 有的时候会立即发出413, 有的时候是文件传输的过程甚至结束后才发出

我说了我只是不知道彻底取消请求的方法, 其他都搞定了

上面的貌似可行

看起来好像是前端用的, 我想要后端用的

如果socket还在, 应该怎么处理呢? 我试着req.socket.end(); 但是没有效果

你可以通过中间件来检查请求的大小,并在文件开始上传之前终止请求。以下是一个示例代码,展示如何使用中间件来拒绝大文件上传:

const express = require('express');
const app = express();

const FILE_SIZE_LIMIT = 1000000; // 1MB

app.use((req, res, next) => {
    let size = 0;
    req.on('data', chunk => {
        size += chunk.length;
        if (size > FILE_SIZE_LIMIT) {
            res.status(413).send('File too large');
            req.connection.destroy(); // 终止连接
        }
    });
    req.on('end', () => next());
});

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

// 路由处理
app.post('/upload', (req, res) => {
    // 处理文件上传逻辑
});

app.listen(3000, () => {
    console.log('Server is running on port 3000');
});

解释:

  1. 中间件:在 app.use 中间件里,我们监听 data 事件来累加数据片段的大小。
  2. 终止请求:如果数据大小超过限制 (FILE_SIZE_LIMIT),则返回状态码 413 并发送消息 “File too large”。然后通过 req.connection.destroy() 终止连接。
  3. 路由处理:只有当数据大小不超过限制时,才会调用下一个中间件或路由处理程序。

这样可以在文件上传过程中尽早地拒绝大文件请求,避免占用过多服务器资源。

回到顶部