I want to create upload with swagger,use DTO and save the binary in my MongoDB
My DTO is:
import { ApiProperty } from '@nestjs/swagger';
import { Expose } from 'class-transformer';
import { IsNotEmpty, IsOptional } from 'class-validator';
export class GatewayDto {
@ApiProperty({ default: 'foo' })
@IsNotEmpty()
@Expose()
name: string;
@ApiProperty({default: 'XXXX:YYYY'})
@IsNotEmpty()
@Expose()
token: string;
@ApiProperty({default: '123'})
@IsNotEmpty()
@Expose()
channelId: string;
@ApiProperty({ default: true })
@IsNotEmpty()
@Expose()
public: string;
@Expose()
@IsNotEmpty()
logo: any;
}
my controller is:
@Post('/')
@ApiConsumes('multipart/form-data')
@ApiBody({
schema: {
type: 'object',
properties: {
name: {
type: 'string',
default: 'foo'
},
token: {
type: 'string',
default: '11:22'
},
channelId: {
type: 'string',
default: '1234'
},
public: {
type: 'string',
default: 'true'
},
logo: {
type: 'string',
format: 'binary',
},
},
},
})
@UseInterceptors(FileInterceptor('logo'))
@HttpCode(HttpStatus.CREATED)
@ApiCreatedResponse(GatewayConfigSwagger.API_CREATE_GATEWAY)
//@Serialize(GatewayDto)
public async create(
@UploadedFile('file') file,
@Body() data: GatewayDto,
@Request() request
) {
console.log(data);
if (file) {
data['logo'] = file.buffer;
}
//return this.gatewayService.create(request.user.userId._id, data);
}
When I create my request, I get this error:
"logo should not be empty"
My curl is:
curl -X 'POST' \
'http://localhost:3001/api/v1/gateways' \
-H 'accept: application/json' \
-H 'Authorization: Bearer xxx \
-H 'Content-Type: multipart/form-data' \
-F 'name=foo' \
-F 'token=11:22' \
-F 'channelId=1234' \
-F 'public=true' \
-F 'logo=@image.png;type=image/png'
If I remove the logo field from DTO I'm able to store my image.
I tried to create a interceptor according to this answer File uploading along with other data in Swagger NestJs
import { BadGatewayException, CallHandler, ExecutionContext, Injectable, NestInterceptor, UnauthorizedException } from "@nestjs/common";
import { catchError, map, Observable, throwError } from "rxjs";
export interface Response<T> {
statusCode: number;
data: T;
}
@Injectable()
export class FileExtender implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
const req = context.switchToHttp().getRequest();
console.log(req.body)
return next.handle();
}
}
and my req.body doesn't have logo field
UPDATE
I updated my interceptor with
import { BadGatewayException, CallHandler, ExecutionContext, Injectable, NestInterceptor, UnauthorizedException } from "@nestjs/common";
import { catchError, map, Observable, throwError } from "rxjs";
export interface Response<T> {
statusCode: number;
data: T;
}
@Injectable()
export class FileExtender implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
const req = context.switchToHttp().getRequest();
req.body['logo'] = req.file.buffer;
console.log(req.body)
return next.handle();
}
}
Now it works, but is it the best practice?