Nestjs 图像验证

Nestjs Image Validation

提问人:lumgaashi 提问时间:11/13/2023 更新时间:11/14/2023 访问量:46

问:

我创建了一个端点来上传头像,控制器是这样的:

  @Post('/avatar')
  @UseInterceptors(
    FileInterceptor('file', {
      storage: diskStorage({
        destination: './public/avatars',
        filename: (req, file, cb) => {
          const { user } = req as unknown as { user: typeof ReqUser };
          const { id } = user as unknown as { id: string };

          const filename: string = id;
          const extension: string = path.parse(file.originalname).ext;
          cb(null, `${filename}${extension}`);
        },
      }),
    }),
  )
  async uploadAvatar(
    @UploadedFile(
      new ParseFilePipe({
        validators: [
          new MaxFileSizeValidator({ maxSize: 5000000 }),
          new FileTypeValidator({ fileType: /image\/(jpeg|png|jpg)/ }),
        ],
      }),
    )
    file: Express.Multer.File,
    @ReqUser() user,
  ) {
    return this.meService.setAvatar(file, user);
  }

我面临的问题是,如果文件无效,将抛出相应的错误,但文件将上传到服务器上,例如,它应该只允许上传带有 .jpg,png,jpg 扩展名的图像,但文件还是会上传?在这种情况下,我做错了什么?

图片 上传 nestjs

评论


答:

0赞 Jay McDoniel 11/14/2023 #1

拦截器在有机会运行其验证之前会完整地完成。您可以在异常筛选器中捕获错误,拉取并获取文件路径,然后在出现异常时删除文件。否则,您可以将文件加载到内存中,并仅在验证通过后才使用模块保存它ParseFilePipereq.filefs

0赞 Eranga Heshan 11/14/2023 #2

就像@jaymcdoniel解释的那样,拦截器将在代码执行函数之前运行。uploadAvatar

要停止将文件上传到服务器的存储,您可以使用 Multer 中的 fileFilter 选项

@Post('/avatar')
@UseInterceptors(
  FileInterceptor('file', {
    fileFilter: (req, file, cb) => {
      // Write your condition below based on the mimetype and/or filename extension.
      if (<YOUR_CONDITION_TO_REJECT_THE_FILE>) {
        cb(null, false);
      } else {
        cb(null, true);
      }
    },
    storage: diskStorage({
      destination: './public/avatars',
      filename: (req, file, cb) => {
        const { user } = req as unknown as { user: typeof ReqUser };
        const { id } = user as unknown as { id: string };

        const filename: string = id;
        const extension: string = path.parse(file.originalname).ext;
        cb(null, `${filename}${extension}`);
      },
    }),
  })
)
async uploadAvatar(
  ...

这将防止 Multer 首先将文件保存在您的服务器中。这样,如果文件类型错误,则无需处理删除文件。

评论

0赞 lumgaashi 11/16/2023
我按照您的指示进行操作,确实有效,但似乎不知何故我有一个错误?因为我无法从 fileFilter 中的请求访问文件的大小。
0赞 Eranga Heshan 11/17/2023
很高兴能帮上忙。 理想情况下,参数应具有“文件信息”下提到的所有属性。当你说你无法访问时,你是什么意思?会返回吗?filefile.sizeundefined
0赞 lumgaashi 11/17/2023
确切地说,它返回为 undefined,即使其中的文件显示它的大小。链接
0赞 Eranga Heshan 11/18/2023
看起来它们在filteFilter函数中没有文件的size属性。您看到的是类型的属性,理想情况下应该对其进行修改以仅显示可用属性(这是其类型的问题)。无论如何,如果要限制文件大小,可以改用 property。limits