Skip to main content

Upload form data with image file in NestJs & MYSQL

 In the previous tutorial, you learned how to filter and count rows in NestJs with TypeORM & MYSQL database. This tutorial teaches you how to upload form data in NestJs & MYSQL. We will create two more routes to insert and update product data. A client app is able to submit form data with an image file. The max image file size in byte is 200000 and it must be jpg, jpeg, png, or gif type. 

To upload files in NestJs, it is required to install Multer typings package.

npm install @types/multer

Create public/uploads folder in the nestjs project to store uploaded files. Then, update the products/ProductsController.tsx file to add the following code:

.............................
import { UseInterceptors,ParseFilePipe, FileTypeValidator,
   MaxFileSizeValidator, UploadedFile} from '@nestjs/common';
import { Express } from 'express';
import { diskStorage } from 'multer';
import * as path from 'path';
import { Product } from 'src/entities/product.entity';
import { ProductserviceService } from 'src/products/productservice.service';
// local storage configuration
var storage = diskStorage({
  destination: function (req, file, callback) {
    callback(null, 'public/uploads');
  },
  filename: function (req, file, callback) {
      callback(null, file.fieldname + '-' + Date.now()+ path.extname(file.originalname));
   
  }
});
// image file validation
var fileUploadValidator= new ParseFilePipe({
  validators: [
    new MaxFileSizeValidator({ maxSize: 200000 }),
    new FileTypeValidator({fileType:  new RegExp('.(jpg|jpeg|png|gif)$')}),

  ],
 fileIsRequired:false,
});

// route to upload form data to insert product data to database
    @Post('add')
    @UseInterceptors(FileInterceptor('image',{
        storage: storage,
       
    }))
    async uploadFile(@Req() req, @Res() res,@UploadedFile(
      fileUploadValidator,
    ) file: Express.Multer.File) {
      const {body} = req;
     
      if(body){
       
        let fname='';
        if(file) fname=file.filename;
        const pro=new Product();
        pro.name=body.name;
        pro.description=body.description;
        pro.price=body.price;
        pro.thumbnail=fname;
        pro.created_at=new Date();
        pro.updated_at=new Date();
        pro.user=1; // later will get user id from logged in user
       

        await this.productsService.create(pro);
        res.send({
          message: 'success',
          data:pro
        });

      }
      else{
        res.send({
          message: 'fail',
          data:{}
        });
      }
     
    }

 // route to upload form data to update product data in database   
    @UseInterceptors(FileInterceptor('image',{
      storage: storage,
    }))
    @Put(':id')
    async update(@Req() req, @Param('id') id: number, @Body() product: Product,
@Res() res, @UploadedFile(fileUploadValidator) file: Express.Multer.File) {
      product.updated_at=new Date();
      let fname='';
      if(file) fname=file.filename;
      if(fname!=='') product.thumbnail=fname;
      const result=await this.productsService.update(id,product);
      if(result){
        res.send({message:'success'});
      }
      else{
        res.send({message:'fail'});
      }
    }
...................

We use diskStorage function from multer package to configure local destination folder (public/uploads) to store updated file and determine the name of uploaded file.

The  ParseFilePipe instance wraps max file size and type validators to restrict the uploaded file max size to 200000 bytes and type to jpg, jpeg, png, and gif. 

A submitted form data has two parts - file and text parts. To upload a file, simply bind the FileInterceptor() interceptor to the route handler and extract file from the request using the @UploadedFile() decorator. The first parameter of FileInterceptor is image field name and the second parameter is storage configurations or local options. You extract text part from the submitted form data using @Body decorator. 

To test adding and updating product with file, open ARC chrome extension.

Add product: 

    - method: POST

    - request url: http://localhost:3000/producst/add

    - header: content-type -> multiplart/form-data

 



Update product that has id equal to 1,

    - method: PUT

    - request url: http://localhost:3000/producst/1

    - header: content-type -> multiplart/form-data



Comments

Popular posts from this blog

Authentication & Role-Based Access Control Using Passport & JWT in NestJs MYSQL

In the earlier tutorials, you learnt to create API endpoints to access MYSQL database and upload files in NestJs. In a real world application, it is common to protect API endpoints by restricting the APIs and grant permissions to only authenticated users.  From a client app, a visitor can register a new account using username, email, password. The default role of the visitor is user. The password is encrypted using bcrypt package. Then after successful registration, he/she can login using username and password. Upon successful login, a valid JWT (JSON Web Token) will be generated and returned to the client. To get permission to access subsequent API endpoints, the client has to send the token in headers to be validated on server. The very popular package to do authentication in NestJs is Passport. In the nestjs app, execute the following commands to install dependencies: npm install --save @nestjs/passport passport passport-local npm install --save-dev @types/passport-local npm install

Filter and count rows in Nestjs & MYSQL database

In the earlier tutorial, you learnt to connect NestJs app with MYSQL database and do migration to add new column to the product table. Now we move on creating APIs to filter data by name with counting the number of products, by id, and delete a specific product from the database.  Execute the following commands to create products module, controller, and service in products folder: npx nest g module products npx nest g controller products npx nest g service products Update products/products.module.ts file to specify the products repository used in the current scope using forFeature method.  import { TypeOrmModule } from '@nestjs/typeorm' ; import { Product } from 'src/entities/product.entity' ; import { ProductsController } from './products.controller' ; import { ProductsService } from './product.service' ; @ Module ({   imports: [ TypeOrmModule . forFeature ([ Product ])],   controllers: [ ProductsController ],   providers: [ ProductServi