不能将 @Res() 与 FilesInterceptor() 一起使用
Posted
技术标签:
【中文标题】不能将 @Res() 与 FilesInterceptor() 一起使用【英文标题】:Can't use @Res() with 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);
【问题讨论】:
【参考方案1】:看,当您使用拦截器时,您正在处理(使用.handle()
)响应流(observable
)而不是它的整个包,但是使用 express @987654324 @ 实际上以某种方式绕过了响应流的整个流程。
nestjs official documents 中也明确提到了这一点:
我们已经知道 handle() 返回一个 Observable。溪流 包含从路由处理程序返回的值,因此我们可以 使用 RxJS 的 map() 运算符轻松地对其进行变异。
警告
响应映射功能不适用于 特定于库的响应策略(直接使用 @Res() 对象 被禁止)。
【讨论】:
【参考方案2】:在嵌套中,您应该始终避免注入 @Res
,因为那样您会丢失很多使嵌套如此出色的东西:拦截器、异常过滤器......
实际上,在大多数情况下,您不需要@Res
,因为nest 会自动处理正确发送响应。
如果你想从控制器方法发送数据,你可以直接返回数据(Promises
和Observables
也会被自动解析)。如果要向客户端发送错误,只需抛出相应的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。以上是关于不能将 @Res() 与 FilesInterceptor() 一起使用的主要内容,如果未能解决你的问题,请参考以下文章