You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在NestJS中使用Multer限制上传文件的总大小?

限制多文件上传总大小的最佳实践

针对NestJS中使用Multer处理多文件上传时的总大小限制需求,这里提供两种实用方案,可根据你的业务场景选择:

方案一:上传过程中实时拦截(推荐用于大文件场景)

这种方式会在文件上传的数据流中实时累加总大小,一旦超过限制立刻中断上传,避免浪费服务器带宽和存储资源。

步骤1:自定义总大小限制的拦截器

创建继承自AnyFilesInterceptor的自定义拦截器,通过监听文件数据流跟踪总大小:

import { Injectable } from '@nestjs/common';
import { AnyFilesInterceptor } from '@nestjs/platform-express';
import { MulterOptions } from '@nestjs/platform-express/multer/interfaces/multer-options.interface';
import * as multer from 'multer';

@Injectable()
export class TotalSizeLimitedFilesInterceptor extends AnyFilesInterceptor {
  private totalUploadedSize = 0;
  private readonly maxTotalSize: number;

  constructor(options: MulterOptions & { maxTotalSize: number }) {
    super(options);
    this.maxTotalSize = options.maxTotalSize;
    this.setupSizeLimitStorage();
  }

  private setupSizeLimitStorage() {
    const originalStorage = this.options.storage || multer.diskStorage({});

    this.options.storage = {
      _handleFile: (req, file, callback) => {
        // 监听文件数据流的chunk,累加总大小
        file.stream.on('data', (chunk) => {
          this.totalUploadedSize += chunk.length;
          if (this.totalUploadedSize > this.maxTotalSize) {
            const error = new Error(`总文件大小超过限制:${this.maxTotalSize / (1024 * 1024)}MB`);
            file.stream.destroy(error);
            callback(error, null);
          }
        });
        // 用原始storage处理文件存储
        originalStorage._handleFile(req, file, callback);
      },
      _removeFile: (req, file, callback) => {
        originalStorage._removeFile(req, file, callback);
      }
    };
  }
}

步骤2:在控制器中使用自定义拦截器

替换原有的AnyFilesInterceptor,添加总大小限制配置:

@Post('send')
@UseInterceptors(
  TotalSizeLimitedFilesInterceptor({
    limits: { fileSize: 2 * 1024 * 1024 }, // 单个文件最大2MB
    maxTotalSize: 10 * 1024 * 1024, // 总文件大小最大10MB
  }),
)
sendEmailWithAttachment(
  @Body() sendEmailPayload: SendEmailPayload,
  @UploadedFiles() files: Array<Express.Multer.File>,
) {
  // 你的业务逻辑
}

方案二:上传完成后检查(适合小文件场景)

如果应用主要处理小文件,对资源消耗不敏感,可以在控制器方法中直接计算所有文件的总大小,超过限制则抛出错误并清理已上传文件:

import { BadRequestException } from '@nestjs/common';
import * as fs from 'fs';

@Post('send')
@UseInterceptors(
  AnyFilesInterceptor({ limits: { fileSize: 2 * 1024 * 1024 } }),
)
sendEmailWithAttachment(
  @Body() sendEmailPayload: SendEmailPayload,
  @UploadedFiles() files: Array<Express.Multer.File>,
) {
  const MAX_TOTAL_SIZE = 10 * 1024 * 1024; // 总大小限制10MB
  const totalSize = files.reduce((sum, file) => sum + file.size, 0);

  if (totalSize > MAX_TOTAL_SIZE) {
    // 清理已上传的文件
    files.forEach(file => fs.unlinkSync(file.path));
    throw new BadRequestException(`总文件大小超过${MAX_TOTAL_SIZE / (1024 * 1024)}MB限制`);
  }

  // 后续业务逻辑
}

补充:错误处理优化

可以注册一个Multer异常过滤器,统一处理上传错误,返回友好提示:

import { ExceptionFilter, Catch, ArgumentsHost, BadRequestException } from '@nestjs/common';
import { MulterError } from 'multer';

@Catch(MulterError)
export class MulterExceptionFilter implements ExceptionFilter {
  catch(exception: MulterError, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse();
    let message = '文件上传失败';

    if (exception.code === 'LIMIT_FILE_SIZE') {
      message = '单个文件大小超过限制';
    } else if (exception.message.includes('总文件大小')) {
      message = exception.message;
    }

    response.status(400).json({
      statusCode: 400,
      message,
      error: '请求参数错误'
    });
  }
}

在控制器上添加@UseFilters(MulterExceptionFilter)即可生效,也可以全局注册该过滤器。

内容的提问来源于stack exchange,提问作者ahbyz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 07:44:57