如何捕获并处理UseInterceptors装饰器抛出的文件校验错误
你遇到的问题本质是Multer的fileFilter回调内抛出的错误默认不会被NestJS内置的异常处理层格式化处理,因此会直接返回原生500错误,错误信息仅会打印在服务端控制台,无法传递到客户端,以下是两种可行解决方案:
方案1:自定义Multer异常过滤器(全局生效,推荐)
该方案无需修改现有业务逻辑,只需新增异常过滤器统一捕获Multer相关错误即可。
步骤1:编写异常过滤器代码
import { ExceptionFilter, Catch, ArgumentsHost, BadRequestException } from '@nestjs/common'; import { MulterError } from 'multer'; @Catch(MulterError, Error) export class MulterExceptionFilter implements ExceptionFilter { catch(exception: MulterError | Error, host: ArgumentsHost) { const ctx = host.switchToHttp(); const response = ctx.getResponse(); // 匹配自定义文件格式校验错误 if (exception.message === 'Only image files are allowed!') { throw new BadRequestException('仅允许上传jpg、jpeg、png、gif格式的图片'); } // 处理其他Multer自带错误,比如文件大小超限等 if (exception instanceof MulterError) { throw new BadRequestException(`文件上传错误:${exception.message}`); } // 其余异常继续向下抛出 throw exception; } }
步骤2:注册过滤器
可根据需求选择全局注册或仅给当前上传接口注册:
- 全局注册(在项目启动文件main.ts中添加)
import { NestFactory } from '@nestjs/core'; import { AppModule } from './app.module'; import { MulterExceptionFilter } from './filters/multer-exception.filter'; async function bootstrap() { const app = await NestFactory.create(AppModule); app.useGlobalFilters(new MulterExceptionFilter()); await app.listen(3000); } bootstrap();
- 仅给当前接口注册(直接添加到控制器方法上)
@Post('/profile-image') @UseFilters(MulterExceptionFilter) // 新增这行即可 @UseInterceptors(FilesInterceptor('img', 1, { fileFilter: imageFileFilter })) async profile( @UploadedFile() file, ): Promise<string> { return await this.prfile.upload(file); }
方案2:修改过滤逻辑,在控制器层手动抛出异常
该方案无需新增过滤器,直接修改现有代码即可实现。
步骤1:修改fileFilter逻辑,不直接抛错,将错误信息挂载到请求对象上
export const imageFileFilter = (req, file, callback) => { if (!file.originalname.match(/\.(jpg|jpeg|png|gif)$/)) { // 把错误信息挂载到req对象,不直接抛出 req.fileValidationError = 'Only image files are allowed!'; return callback(null, false); } callback(null, true); };
步骤2:修改控制器代码,判断校验结果后手动抛出异常
import { BadRequestException, Req } from '@nestjs/common'; @Post('/profile-image') @UseInterceptors(FilesInterceptor('img', 1, { fileFilter: imageFileFilter })) async profile( @UploadedFile() file, @Req() req: Request // 注入当前请求对象 ): Promise<string> { // 判断是否存在文件校验错误 if (req['fileValidationError']) { throw new BadRequestException(req['fileValidationError']); } return await this.prfile.upload(file); }
两种方案实现后,文件格式不符合要求时接口会返回400状态码和对应的错误提示,不会再返回500内部错误。
内容的提问来源于stack exchange,提问作者Hamza Zahidul Islam
相关产品推荐
相关产品推荐

