NestJS如何验证多上传文件的总大小不超过限制?
NestJS多附件上传总大小限制与文件验证方案
一、基础配置:通过Multer限制单个文件大小
先在文件上传拦截器的配置里,设置单个文件的大小上限,同时可提前过滤非法文件类型:
import { Controller, Post, UploadedFiles, UseInterceptors } from '@nestjs/common'; import { FilesInterceptor } from '@nestjs/platform-express'; import { diskStorage } from 'multer'; @Post('/text') @UseInterceptors(FilesInterceptor('files', 10, { // 第二个参数为允许上传的最大文件数量 storage: diskStorage({ destination: './uploads', filename: (req, file, cb) => { const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9); cb(null, `${file.fieldname}-${uniqueSuffix}`); }, }), limits: { fileSize: 5 * 1024 * 1024, // 单个文件最大5MB(若总大小限制5MB,可设更小值) }, fileFilter: (req, file, cb) => { // 过滤允许的文件MIME类型 const allowedTypes = ['image/jpeg', 'image/png', 'application/pdf']; if (allowedTypes.includes(file.mimetype)) { cb(null, true); } else { cb(new Error('仅允许上传JPG/PNG/PDF类型文件'), false); } }, })) async addText(@UploadedFiles() files) { console.log("The files", files); }
二、验证所有文件总大小不超过5MB
Multer无直接总大小限制配置,可通过自定义管道实现:
- 创建自定义验证管道
FileTotalSizePipe:
import { PipeTransform, Injectable, BadRequestException } from '@nestjs/common'; @Injectable() export class FileTotalSizePipe implements PipeTransform { private readonly maxTotalSize = 5 * 1024 * 1024; // 5MB换算为字节 transform(files: Express.Multer.File[]) { const totalSize = files.reduce((sum, file) => sum + file.size, 0); if (totalSize > this.maxTotalSize) { throw new BadRequestException(`所有文件总大小不能超过5MB`); } return files; } }
- 在接口中引入该管道:
@Post('/text') @UseInterceptors(FilesInterceptor('files', 10, { // 保留之前的multer配置 })) async addText(@UploadedFiles(FileTotalSizePipe) files) { console.log("The files", files); }
三、扩展多维度文件验证
如果需要更全面的校验(比如文件数量、单个文件二次校验、扩展名验证),可扩展管道逻辑:
import { PipeTransform, Injectable, BadRequestException } from '@nestjs/common'; @Injectable() export class FullFileValidationPipe implements PipeTransform { private readonly maxTotalSize = 5 * 1024 * 1024; private readonly maxSingleSize = 2 * 1024 * 1024; // 单个文件最大2MB private readonly maxFileCount = 5; // 最多上传5个文件 private readonly allowedExtensions = ['.jpg', '.jpeg', '.png', '.pdf']; transform(files: Express.Multer.File[]) { // 验证文件数量 if (files.length > this.maxFileCount) { throw new BadRequestException(`最多允许上传${this.maxFileCount}个文件`); } // 单个文件大小与扩展名校验 files.forEach(file => { if (file.size > this.maxSingleSize) { throw new BadRequestException(`文件${file.originalname}大小不能超过2MB`); } const ext = file.originalname.toLowerCase().slice(file.originalname.lastIndexOf('.')); if (!this.allowedExtensions.includes(ext)) { throw new BadRequestException(`文件${file.originalname}类型不允许,仅支持${this.allowedExtensions.join(', ')}`); } }); // 总大小校验 const totalSize = files.reduce((sum, file) => sum + file.size, 0); if (totalSize > this.maxTotalSize) { throw new BadRequestException(`所有文件总大小不能超过5MB`); } return files; } }
之后在接口中替换使用FullFileValidationPipe即可。
内容的提问来源于stack exchange,提问作者Zephyr
相关产品推荐
相关产品推荐

