不能将 @Res() 与 FilesInterceptor() 一起使用
Can't use @Res() with FilesInterceptor()
我正在尝试使用内置 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);
}
}
在 nest 中,你应该始终避免注入 @Res
因为那样你会失去很多让 nest 如此伟大的东西:拦截器,异常过滤器,...
实际上,在大多数情况下您不需要 @Res
,因为 nest 会自动处理正确发送响应。
如果你想从控制器方法发送数据,你可以 return 数据(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) {
看,当你使用拦截器时,你正在处理(使用 .handle()
)响应流(observable
)而不是整个包,但是 使用 express @Res
实际上是以某种方式绕过响应流的整个流程。
这在nestjs official documents中也明确提到:
We already know that handle() returns an Observable. The stream
contains the value returned from the route handler, and thus we can
easily mutate it using RxJS's map() operator.
WARNING
The response mapping feature doesn't work with the
library-specific response strategy (using the @Res() object directly
is forbidden).
我正在尝试使用内置 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);
}
}
在 nest 中,你应该始终避免注入 @Res
因为那样你会失去很多让 nest 如此伟大的东西:拦截器,异常过滤器,...
实际上,在大多数情况下您不需要 @Res
,因为 nest 会自动处理正确发送响应。
如果你想从控制器方法发送数据,你可以 return 数据(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) {
看,当你使用拦截器时,你正在处理(使用 .handle()
)响应流(observable
)而不是整个包,但是 使用 express @Res
实际上是以某种方式绕过响应流的整个流程。
这在nestjs official documents中也明确提到:
We already know that handle() returns an Observable. The stream contains the value returned from the route handler, and thus we can easily mutate it using RxJS's map() operator.
WARNING
The response mapping feature doesn't work with the library-specific response strategy (using the @Res() object directly is forbidden).