NestJS POST接收ArrayBuffer时req.body为空/undefined解决方案
从Angular客户端向NestJS服务端直传非multipart格式文件,文件对应content-type为application/pdf、image/png、image/jpeg等标准MIME类型,同套请求逻辑对接Java SpringBoot接口可正常运行。但在NestJS中使用如下POST接口接收数据时,@Body()装饰器取到的值为空对象{},req.body值为undefined,无法获取任何有效请求数据:
@Post('/uploadExportFile') uploadAttachment(@Req() req: Request, @Body() attachment: ArrayBuffer): any { console.log(attachment); return {}; }
业务侧要求不改动前端现有传输格式,最终需要将接收的文件转回Base64格式,适配下游仅接收byte[]类型参数的Java API。
NestJS默认全局启用JSON格式请求体解析器,无法正确解析二进制格式的raw请求体,导致目标路由无法读取原始二进制传输数据。
针对需要接收raw二进制数据的路由单独配置raw-body解析规则,覆盖默认的JSON解析逻辑即可,具体操作步骤如下:
创建请求体解析中间件
新建raw-body.middleware.ts作为二进制请求体解析中间件,代码如下:import { Injectable, NestMiddleware } from '@nestjs/common'; import { Request, Response } from 'express'; import * as bodyParser from 'body-parser'; @Injectable() export class RawBodyMiddleware implements NestMiddleware { use(req: Request, res: Response, next: () => any) { bodyParser.raw({type: '*/*'})(req, res, next); } }同目录下创建JSON解析中间件
JsonBodyMiddleware,仅需将上述代码中bodyParser.raw({type: '*/*'})替换为bodyParser.json()即可,用于处理普通业务接口的JSON格式请求体。配置中间件路由匹配规则
在app.module.ts中指定不同路由对应的解析器,让文件上传接口走raw二进制解析,其余接口走默认JSON解析:export class AppModule implements NestModule { public configure(consumer: MiddlewareConsumer): void { consumer .apply(RawBodyMiddleware) .forRoutes({ path: '/uploadExportFile', method: RequestMethod.POST, }) .apply(JsonBodyMiddleware) .forRoutes('*'); } }关闭框架默认全局bodyParser
在main.ts启动应用时,关闭内置的默认请求体解析配置,避免和自定义中间件冲突:const app = await NestFactory.create(AppModule, { bodyParser: false })
补充说明:高版本NestJS提供了原生raw-body配置项,可直接在框架配置中开启该能力,无需手动编写中间件。
内容的提问来源于stack exchange,提问作者strakz

