Accept form-data in Nest.js
Asked Answered
V

4

23

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

Veinlet answered 13/9, 2020 at 14:48 Comment(1)
This question should include the actual code instead of images of code.Ludwigg
E
48

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);
}
Euhemerism answered 15/9, 2020 at 19:5 Comment(3)
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?Oney
To accept multipart/form-data but not allow any files to be uploaded, use the NoFilesInterceptor. Learn more from hereVillareal
How could someone go about validating the form data being sent from the User? I can't seem to find a way to set up a validator pipe that can be applied on the file field + the additional fields that may have been included in the body.Rusk
P
1

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;

}
Pedicure answered 28/4, 2023 at 18:56 Comment(1)
How do you validate nested dtos?Impenitent
Q
1

if you dont want to recieve files and but fields in form data you can use like this

@Post("register")
@UseInterceptors(NoFilesInterceptor())
async register(
@Body() body: any,
@Res() res: Response,
@Req() req: Request
)

and make sure in main.ts add this

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

`

Quinquereme answered 30/11, 2023 at 13:22 Comment(0)
M
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;
  }
}
Misguided answered 9/8, 2023 at 6:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.