【问题标题】:Can't use @Res() with FilesInterceptor()不能将 @Res() 与 FilesInterceptor() 一起使用
【发布时间】:2019-09-01 17:46:16
【问题描述】:

我正在尝试使用内置 multer 上传文件,然后将响应发送回用户以确认成功或失败。直到今天一切都很好,当我尝试上传响应时不会出现。经过一番挖掘,我发现当我将@res 与@UploadedFile 一起使用时,它不会执行控制器。我是 Nest.js 的新手。

工作。

@Post('uploads/avatar')
async uploadFile(@Req() req, @UploadedFile() avatar) {
  console.log(req.body);
  if (!req.body.user_id) {
    throw new Error('id params not found.');
  }
  try {
    const resultUpload = await this.userService.uploadUserImage(
      req.body.user_id,
      avatar, 
    ); // returns the url for the uploaded image
    return resultUpload;
  } catch (error) {
    console.log(error);
    return error;
  }
}

不工作。

@Post('uploads/avatar')
async uploadFile(@Req() req, @UploadedFile() avatar, @Res() res) {
  console.log(req.body);
  if (!req.body.user_id) {
    throw new Error('id params not found.');
  }
  try {
    const resultUpload = await this.userService.uploadUserImage(
      req.body.user_id,
      avatar,      
    ); // returns the url for the uploaded image
    return resultUpload;
   res.send(resultUpload);
  } catch (error) {
    console.log(error);
    res.send(error);
  }
}

【问题讨论】:

    标签: javascript node.js typescript multer nestjs


    【解决方案1】:

    看,当您使用拦截器时,您正在处理(使用.handle())响应流(observable)而不是它的整个包,但是使用 express @987654324 @ 实际上以某种方式绕过了响应流的整个流程。

    nestjs official documents 中也明确提到了这一点:

    我们已经知道 handle() 返回一个 Observable。溪流 包含从路由处理程序返回的值,因此我们可以 使用 RxJS 的 map() 运算符轻松地对其进行变异。

    警告

    响应映射功能不适用于 特定于库的响应策略(直接使用 @Res() 对象 被禁止)。

    【讨论】:

      【解决方案2】:

      在嵌套中,您应该始终避免注入 @Res,因为那样您会丢失很多使嵌套如此出色的东西:拦截器、异常过滤器......

      实际上,在大多数情况下,您不需要@Res,因为nest 会自动处理正确发送响应。

      如果你想从控制器方法发送数据,你可以直接返回数据(PromisesObservables 也会被自动解析)。如果要向客户端发送错误,只需抛出相应的HttpException,例如404 -> NotFoundException:

      @Post('uploads/avatar')
      async uploadFile(@Req() req, @UploadedFile() avatar) {
        if (!req.body.user_id) {
          // throw a 400
          throw new BadRequestException('id params not found.');
        }
        try {
          const resultUpload = await this.userService.uploadUserImage(
            req.body.user_id,
            avatar, 
          );
          return resultUpload;
        } catch (error) {
          if (error.code === 'image_already_exists') {
            // throw a 409
            throw new ConflictException('image has already been uploaded');
          } else {
            // throw a 500
            throw new InternalServerException();
          }
        }
      }
      

      如果由于某种原因必须在此处注入@Res,则不能使用FilesInterceptor。然后你必须自己配置multer中间件。


      旁注

      您可以创建一个自定义装饰器来访问userId

      import { createParamDecorator } from '@nestjs/common';
      
      export const UserId = createParamDecorator((data, req) => {
        if (!req.body || !req.body.user_id) {
          throw new BadRequestException('No user id given.')
        }
        return req.body.user_id;
      });
      

      然后像这样在你的控制器方法中使用它:

      @Post('uploads/avatar')
      async uploadFile(@UserId() userId, @UploadedFile() avatar) {
      

      【讨论】:

      • 我对这个概念有疑问,但这一切都消除了。非常感谢。
      • 您有什么疑问?嵌套的一大优点是您不必直接处理响应对象,而是可以使用框架提供的更高级别的抽象。
      • 我正在开发一个api。我在大多数控制器中都使用了@Res,但是当我使用@UploadedFile() 进行尝试时,我没有工作。我怀疑这是因为他们在框架中实现的 multer。
      • 我如何使用自动发送响应返回一个 json 对象? { status: "OK", mesage: "Successful"}
      • 只要返回一个javascript对象,它就会自动序列化为JSON。
      猜你喜欢
      • 2011-12-11
      • 1970-01-01
      • 2019-02-20
      • 2014-06-20
      • 2020-03-06
      • 2017-04-15
      • 2019-07-09
      • 2017-10-23
      • 1970-01-01
      相关资源
      最近更新 更多