21

I have written auth routes in Nestjs and wanted to use it with the form-data. I got it working with URL-encoded-form-data, JSON, text, but not receiving anything in the body when I use form-data and really want it to work with form-data as on the front-end I am hitting the route with form-data. I have tried every way I could find on the web, but none of them helped me in this case. so after hours of searching and trying when I didn't get any lead I am posting my question here. Any Kind of Help is appreciated.

Code of signup endpoint:

@Post('native/loginWithPhone')
async loginWithPhoneNative(@Body() { phone }: LoginWithPhoneDto) {
    return await this.securityCodeService.sendSecurityCodeNative(phone, 'otp');
}

@Post('signup')
async signup(@Request() req, @Body() body) {
    console.log(req)
    console.log(body)
    return await req.body
    // return await this.authService.signupWithEmail({
    //   email,
    //   password,
    //   dob,
    //   role: process.env.ROLE_USER,
    // });
}

Main.ts configurations :

import * as bodyParser from 'body-parser'
import * as multer from 'multer';
global. fetch = require('node-fetch');

async function bootstrap() {
    require('dotenv').config();

    const app = await NestFactory.create(AppModule, {
    bodyParser: true,
});

await app.init();
app.enableCors();

app.use(multer)
app.use(bodyParser.urlencoded({extended: true}))
app.use(bodyParser.text({type: 'text/html'}))
app.use(bodyParser.json())
app.useGlobalPipes(new ValidationPipe());

empty body I am getting on postman empty body I am getting on postman

Logarr
  • 2,120
  • 1
  • 17
  • 29
usama_akram
  • 237
  • 1
  • 2
  • 7

3 Answers3

41

NestJS provides a built-in multipart/form-data parser which you can access using a FileInterceptor.

Here's an example of how you'd read a single file (as you've shown in your screenshot):

@Post('signup')
@UseInterceptors(FileInterceptor('<name of file here - asdasd in your screenshot>'))
signup(@UploadedFile() file, @Body() body) {
  console.log(file);
  console.log(body);
}
BinaryButterfly
  • 18,137
  • 13
  • 50
  • 91
eol
  • 23,236
  • 5
  • 46
  • 64
  • If I dont need a file name, the FileInterceptor still need a name string. Is it the best practice if put any string name here in FileInterceptor in this case? – andyCao Aug 09 '22 at 08:55
0

I recommend the npm package named "nestjs-form-data".

You only need use npm install nestjs-form-data or yarn add nestjs-form-data respectively.

The code that solve the problem is something like that:

The module:...

@Module({
  imports: [
    NestjsFormDataModule.config({ storage: MemoryStoredFile }),
  ],
  controllers: [],
  providers: [],
})
export class AppModule {
}

The controller:...

@Controller()
export class NestjsFormDataController {


  @Post('load')
  @FormDataRequest({storage: MemoryStoredFile})
  getHello(@Body() testDto: FormDataTestDto): void {
    console.log(testDto);
  }
}

You can make validations like that:

import { FileSystemStoredFile, HasMimeType, IsFile, MaxFileSize } from 'nestjs-form-data';


export class FormDataTestDto {

  @IsFile()
  @MaxFileSize(1e6)
  @HasMimeType(['image/jpeg', 'image/png'])
  avatar: FileSystemStoredFile;

}
eriker75
  • 31
  • 2
0

Here are the implementations for accepting form-data:

import { Controller, Post, UploadedFiles, UseInterceptors, Body, Get } from '@nestjs/common';
import { FilesInterceptor } from '@nestjs/platform-express';

@Controller('api/portal/file')
export class GCPController {
  constructor(private gcpService: GCPService) {}

  @Post('/multiple')
  @UseInterceptors(FilesInterceptor('files'))
  async uploadFiles(@UploadedFiles() files: Array<Express.Multer.File>, @Body() body: any) {
    console.log('body :', body);
    const req: FileDataReq = {
      files,
      ...body,
    };
    return req;
  }
}
Shubham Verma
  • 8,783
  • 6
  • 58
  • 79