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,
})
}
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);
}
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();
}
}
The solution that works for me was to create a class containing the API references I will be using and to set one of those fields as the File
.
storage-object.dto.ts
export class StorageObjectDto {
@ApiProperty({ required: false })
@IsString()
comment?: string
@ApiProperty({ type: 'string', format: 'number', required: false })
@IsNumber()
outletId?: number
@ApiProperty({ type: 'string', format: 'binary', required: true })
file: Express.Multer.File
}
Using the implementation suggested on the nestJs docs, I can extract the file based on the associated key within the object.
In this case, the key is file
object.controller.ts
@Version('1')
@Post('upload')
@ApiConsumes('multipart/form-data')
@UseInterceptors(FileInterceptor('file'))
uploadFile(@Body() data: StorageObjectDto, @UploadedFile() file: Express.Multer.File): void {
console.log({ data, file })
}
Once you call the endpoint you should see the following output in your console log
{
data: FileDataDto {
comment: 'This is a test comment',
outletID: 123
},
file: {
fieldname: 'file',
originalname: 'placeholder.png',
encoding: '7bit',
mimetype: 'image/png',
buffer: <Buffer 89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 00 00 01 f4 00 00 01 f4 04 03 00 00 00 39 f8 c2 b9 00 00 00 1b 50 4c 54 45 cc cc cc 96 96 96 9c 9c 9c ... 1069 more bytes>,
size: 1119
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With