Search code examples
nestjsnestjs-swagger

File uploading along with other data in Swagger NestJs


I want to send file along with JSON

{
    "comment" : "string",
    "outletId" : 1
}

The help I got from Documentation is

requestBody:
    content:
      multipart/form-data:
        schema:
          type: object
          properties:
            orderId:
              type: integer
            userId:
              type: integer
            fileName:
              type: string
              format: binary

I don't know where to put this schema. I have tried putting it inside @ApiProperty() in DTO as well as in @ApiOperations but could not resolve the issue.

Below is the function I want to capture file content in.

@Post('/punchin')
@ApiConsumes('multipart/form-data')
@ApiOperation({ summary: 'Attendance Punch In' })
@UseInterceptors(CrudRequestInterceptor, ClassSerializerInterceptor, FileInterceptor('file'))
@ApiImplicitFile({ name: 'file' })
async punchInAttendance( @Body() body: PunchInDto, @UploadedFile() file: Express.Multer.File ): Promise<Attendance> {
    const imageUrl = await this.s3FileUploadService.upload(file)
    console.log(body, imageUrl)
    return await this.service.punchInAttendance({
      comment: body.punchInComment,
      outletId: body.outletId,
      imgUrl: imageUrl,
    })
  }

Solution

  • use @ApiBody because body keeps your data.

      @Post('upload')
      @ApiConsumes('multipart/form-data')
      @ApiBody({
        schema: {
          type: 'object',
          properties: {
            comment: { type: 'string' },
            outletId: { type: 'integer' },
            file: {
              type: 'string',
              format: 'binary',
            },
          },
        },
      })
      @UseInterceptors(FileExtender)
      @UseInterceptors(FileInterceptor('file'))
      uploadFile2(@UploadedFile('file') file) {
        console.log(file);
      }
    

    screenshot

    I get in console:

    {
      fieldname: 'file',
      originalname: 'dart.txt',
      encoding: '7bit',
      mimetype: 'text/plain',
      buffer: <Buffer 20 0a 69 6d  ... 401 more bytes>,
      size: 451,
      comment: 'some comment',
      outletId: 123456
    }
    

    Because FileInterceptor removes body params, I used FileExtender interceptor, to pack comment and outletId in file properties.

    @Injectable()
    export class FileExtender implements NestInterceptor {
      intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
        const req = context.switchToHttp().getRequest();
        req.file['comment'] = req.body.comment;
        req.file['outletId'] = Number(req.body.outletId);
        return next.handle();
      }
    }