使用NestJS/Multer上传文件时无法在FileInterceptor的fileFilter中访问buffer
问题原因与解决方案
为什么fileFilter中无法访问file.buffer?
Nest的FileInterceptor基于Multer实现,而Multer的fileFilter回调执行时机早于文件内容被读取到内存/磁盘的阶段。此时file对象仅包含文件的元数据(如originalname、mimetype、fieldname等),还没有加载文件的实际内容,因此buffer属性为undefined。
而控制器中@UploadedFile()装饰器拿到的file对象,是Multer完成文件读取后的结果——此时文件内容已被加载到内存(默认内存存储),所以buffer属性存在且可用。
解决方案
根据你的需求场景,有两种常见处理方式:
1. 仅校验文件元数据(如类型)
如果只是需要过滤文件类型,直接使用fileFilter中的file.mimetype即可,无需访问buffer:
@UseInterceptors(FileInterceptor('file', { fileFilter: (req, file, cb) => { // 允许PNG和JPG文件 const allowedMimeTypes = ['image/png', 'image/jpeg']; if (allowedMimeTypes.includes(file.mimetype)) { cb(null, true); } else { cb(new BadRequestException('仅支持PNG/JPG格式'), false); } } })) async testUpload(@UploadedFile() file) { console.log(file.buffer); }
2. 需要基于文件内容校验(如签名、格式真实性)
如果必须验证文件实际内容(比如判断是否为真实图片而非改后缀的文件),需要在文件被读取完成后进行校验,推荐使用Nest的管道(Pipe):
// 定义文件校验管道 import { PipeTransform, Injectable, BadRequestException } from '@nestjs/common'; import { Express } from 'express'; @Injectable() export class FileContentValidationPipe implements PipeTransform { transform(file: Express.Multer.File) { // 此处可访问file.buffer,进行内容校验 const isRealPng = this.checkPngSignature(file.buffer); if (!isRealPng) { throw new BadRequestException('文件不是有效的PNG格式'); } return file; } // 校验PNG文件的魔数(magic number) private checkPngSignature(buffer: Buffer): boolean { const pngMagicNumber = buffer.slice(0, 8).toString('hex'); return pngMagicNumber === '89504e470d0a1a0a'; } } // 在控制器中使用管道 @Post('file') @UseInterceptors(FileInterceptor('file')) async testUpload(@UploadedFile(FileContentValidationPipe) file) { console.log(file.buffer); }
你也可以通过自定义Multer的storage来实现,但管道的方式更符合Nest的架构设计,代码解耦性更好。
内容的提问来源于stack exchange,提问作者jaqarrick
相关产品推荐
相关产品推荐

