无法捕获由FilesInterceptor引发的BadRequestException

0sgqnhkj  于 2022-09-21  发布在  Node.js
关注(0)|答案(2)|浏览(194)

我正在尝试设置一个逻辑来使用Multer保存上传的文件。为此,我遵循Nestjs教程并使用“FilesInterceptor”拦截器。

控制器文件:

import {
    Controller,
    FileValidator,
    ParseFilePipe,
    Post,
    UploadedFiles,
    UseInterceptors
} from '@nestjs/common';
import { FilesInterceptor } from '@nestjs/platform-express';
import { Public } from 'src/auth/decorators/public.decorator';
import { MimeTypeValidationPipe } from './pipes/mimetype.validation.pipe';

const ACCEPTED_FILE_MIMETYPES = ["image/jpeg", "image/jpg", "image/png"]
const validators: FileValidator[] = [
    new MimeTypeValidationPipe({ accepted: ACCEPTED_FILE_MIMETYPES })
];

@Controller('uploads')
export class UploadsController {

    @Public()
    @Post("/")
    @UseInterceptors(FilesInterceptor("files"))
    public async create(
        @UploadedFiles(new ParseFilePipe({ validators })) 
        files: Express.Multer.File[]
    ){
        files[0].originalname
        const filenames = files.map(({ originalname }) => originalname)
        return { filenames };
    }
}

但是,当我测试服务器在上传的文件数量超过限制时的行为时,服务器返回错误500(就好像错误没有得到处理一样)。然后,我尝试使用如下所示的ExcepetionFilter来捕获它:

@Catch()
class TestFilter implements ExceptionFilter {
    catch(exception: any, host: ArgumentsHost) {
        console.debug(exception)
        if(exception instanceof HttpException) console.debug("This is an HTTP Exception !");
        else console.debug("This is NOT an HTTP Exception");
        const response = host.switchToHttp().getResponse<Response>();
        return response.status(500).json({statusCode: 500 , message: "ERROR" });
    }
}

我得到了以下输出:

BadRequestException: Too many files
    at transformException (~/development/Nest/nestapi/node_modules/@nestjs/platform-express/multer/multer/multer.utils.js:19:20)
    at ~/development/Nest/nestapi/node_modules/@nestjs/platform-express/multer/interceptors/files.interceptor.js:18:73
    at ~/development/Nest/nestapi/node_modules/@nestjs/platform-express/node_modules/multer/lib/make-middleware.js:53:37
    at AsyncResource.runInAsyncScope (node:async_hooks:202:9)
    at listener (~/development/Nest/nestapi/node_modules/@nestjs/platform-express/node_modules/on-finished/index.js:170:15)
    at onFinish (~/development/Nest/nestapi/node_modules/@nestjs/platform-express/node_modules/on-finished/index.js:101:5)
    at callback (~/development/Nest/nestapi/node_modules/@nestjs/platform-express/node_modules/ee-first/index.js:55:10)
    at IncomingMessage.onevent (~/development/Nest/nestapi/node_modules/@nestjs/platform-express/node_modules/ee-first/index.js:93:5)
    at IncomingMessage.emit (node:events:539:35)
    at endReadableNT (node:internal/streams/readable:1345:12) {
  response: { statusCode: 400, message: 'Too many files', error: 'Bad Request' },
  status: 400
}
This is NOT an HTTP Exception

筛选器指示它不是HTTPException。然而,在深入研究FilesInterceptor.ts代码时,我注意到捕获的错误是由一个小的实用函数“TransException”处理的,该函数应该将Multer错误转换为HttpException(取决于Multer返回的错误代码)

muter.utils.ts文件(来自Nest repo)

import {
  BadRequestException,
  HttpException,
  PayloadTooLargeException,
} from '@nestjs/common';
import { multerExceptions } from './multer.constants';

export function transformException(error: Error | undefined) {
  if (!error || error instanceof HttpException) {
    return error;
  }
  switch (error.message) {
    case multerExceptions.LIMIT_FILE_SIZE:
      return new PayloadTooLargeException(error.message);
    case multerExceptions.LIMIT_FILE_COUNT:
    case multerExceptions.LIMIT_FIELD_KEY:
    case multerExceptions.LIMIT_FIELD_VALUE:
    case multerExceptions.LIMIT_FIELD_COUNT:
    case multerExceptions.LIMIT_UNEXPECTED_FILE:
    case multerExceptions.LIMIT_PART_COUNT:
      return new BadRequestException(error.message);
  }
  return error;
}

我不明白为什么我的过滤器(和NestJS的unhandledExceptionFilter)不能检测到这个异常,因为对我来说,它应该是HttpException的一个示例。

你能帮帮我吗?

诚挚的问候

9o685dep

9o685dep1#

您的项目中可能包含两个@nestjs/Common副本。创建错误的代码正在使用一个副本,而您的异常筛选器正在使用另一个副本。当您的代码检查instanceof时,它检查异常是否是来自@nestjs/Common的It‘s副本的HttpException的示例,但不是,它是来自@nestjs/Common的另一个副本的HttpException的示例。这称为“多领域”(请参阅https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/instanceof#instanceof_and_multiple_realms).

解决这个问题的方法是确保您的项目中只有一个@nestjs/Common副本。通常,您有2个是因为您有2个不同版本规格的Package.json文件(例如,一个Package.json中的“@nestjs/Common”:“^8.0.0”,而另一个中的“@nestjs/Common”:“^9.0.0”)。您可能需要使用overrides键来强制依赖项使用与您在其他地方使用的版本相同的版本。

希望这能帮上忙!

9wbgstp7

9wbgstp72#

抱歉的!

我想问题出在我身上。

Multer的LTS版本(1.4.4-lts.1)有缺陷。因此,我决定降级到1.4.4(没有出现问题的错误的版本)。但要做到这一点,我必须通过在node_modules/@nest/platform-express目录中执行npm install multer@1.4.4来手动降级嵌套依赖项。

但就在那时,Nestjs开始对我的错误进行糟糕的格式化。

有趣的是,返回(npm install multer@1.4.4-lts.1node_modules/@nest/platform-express目录)并不能解决问题(错误处理仍然很糟糕),我不得不删除node_modules/@nest/platform-express文件夹并从项目的根目录重新安装包,以使一切恢复正常(当然,还有LTS版本的错误)。

好奇怪啊。

相关问题