File uploading example using NestJS and Angular 11 - Part 1




The NestJS framework is becoming very popular in the industry because it provides many features for JavaScript-based micro-services. NestJS framework is very similar to Spring Boot. If you are familiar with Spring Boot, it will be very easy to go through with NestJS. You can find everything about NestJS from NestJS documentation. 

Here I am going to explain a CSV file upload service using NestJS as the back-end and Angular 11 as the front-end. I hope to add more features to this application in future posts. 


Why NestJS?

  • An open-source framework to create efficient and scalable server-side applications with NodeJS.
  • Fully supported for TypeScript and based on ExpressJS.
  • The important thing about NestJS is, it provides the application architecture to create highly available, scalable, maintainable, testable, and loosely coupled server-side applications.

The application overview

  • Create a REST API using NestJS
  • Use TypeORM to save CSV file data into the database
  • Create a client application using Angular 11

Used technologies

  • NestJS
  • Angular 11
  • TypeORM
  • Postgres DB

Prerequisites 

Here I mention the version that I am using. Sometimes the versions can differ from what you are using. 
  • Install NodeJS v14.16.1 with NPM version 7.18.1
  • Install NestJS CLI 7.6.0
  • Install Angular CLI 11.2.12
  • Basic knowledge about NodeJS and TypeScipt

Create a new NestJS application using NestJS CLI

  • First, you need to install NestJS CLI on your local machine.
  • Then hit the following command in the terminal to create a NestJS micro-service.
  • automobile-backend is my application name and npm as my package manager.

nest new automobile-backend

Create the basic folder structure and required files

  • Open the project in your IDE. I am using Visual Studio Code.
  • Create a module called "automobile" to organize components. 
nest g module automobile

  • Inside the automobile module, I create new files as a controller and service.
nest g controller automobile

nest g service automobile

  • My terminal window will look like this

  • As you can see, it will automatically create spec files for testings and updated automobile.module.ts files.
  • Since I am not going to create test cases here, I deleted spec files to make the application clear.
  • Then I create a new file "vehicle.ts" as an entity to specify the properties of the vehicle. Up to now, it is an empty file.

Set up TypeORM and DB configurations

  • I am using a local Postgres DB instance for data operations in this example. I have already installed PostgreSQL 13 and pgAdmin 4.
  • TypeORM is one of the best ORM frameworks for NodeJS based applications.
  • Import TypeORM module with Postgres for NestJS.

npm i --save @nestjs/typeorm typeorm pg

  • Now let's create a new module for database configurations.
nest g module database

  • Then you can add relevant properties to the configuration file.

        import { Module } from '@nestjs/common';
        import { TypeOrmModule } from '@nestjs/typeorm';
        import { Vehicle } from 'src/automobile/vehicle';

        @Module({
        imports: [TypeOrmModule.forRoot({
        type: 'postgres',
        host: 'localhost',
         port: 5432,
        username: 'postgres',
        password: '1234',
        database: 'TestDB',
        entities: [Vehicle],
        synchronize: true
        })]    
        })
        export class DatabaseModule {}

  • The properties can be easily understood. 
  • Then you need to add the TypeORM module as an import of the Automobile module.

        import { Module } from '@nestjs/common';
        import { AutomobileController } from './automobile.controller';
        import { AutomobileService } from './automobile.service';
        import { TypeOrmModule } from '@nestjs/typeorm';
        import { Vehicle } from './vehicle';

        @Module({
        controllers: [AutomobileController],
        providers: [AutomobileService],
        imports: [TypeOrmModule.forFeature([Vehicle])]
        })
        export class AutomobileModule {}


  • Now we can complete the Vehicle entity that we created earlier. 

Create an entity

  • Now I am going to complete the Vehicle entity.
  • Please check below entity class

        import { Column, Entity, PrimaryColumn } from "typeorm";

        @Entity('vehicle')
        export class Vehicle{

        @PrimaryColumn()
        private id: number;

        @Column('varchar')
        private make: string;

        @Column('varchar')
        private model: string;

        @Column('integer')
        private year: number;

        @Column('varchar')
        private engineNumber: string;
        }


Create a REST API

  • Now we can create a simple REST endpoint in our controller.
  • Before doing this we need to import few modules since we are planning a CSV file upload.

Install multer

  • For a better type safety, let's install multer package
npm i -D @types/multer


Create an API

  • Then let's create a new API for file uploading. 
  • Now my controller looks like this. I will explain one by one.

        import { Controller, Post, UploadedFile, UseInterceptors } from '@nestjs/common';
        import { FileInterceptor } from '@nestjs/platform-express';
        import { extname } from 'path';
        import { diskStorage } from 'multer';
        import { AutomobileService } from './automobile.service';

        @Controller('/api/vehicles')
        export class AutomobileController {

        constructor(private autoService: AutomobileService){}

        @Post('/upload')
        @UseInterceptors(FileInterceptor("csv", {
        storage: diskStorage({
        destination: './csv',
        filename: (req, file, cb) => {
       const randomName = Array(32).fill(null).map(() => (Math.round(Math.random() * 16)).toString(16)).join('')
        cb(null, `${randomName}${extname(file.originalname)}`)
        }
        })
        }))
        uploadCsv(@UploadedFile() file){
        this.autoService.saveFile(file);
        }
        }

  • @Controller('/api/vehicles')
    • This will make a class as a controller, very similar to Spring Boot @RestController.
    • Inside brackets, you can set the path.
  • constructor
    • In the constructor, I injected the AutomobileService.
  • @Post('/upload')
    • The file uploading process is a Post operation.
    • @Post is a standard decorator in NestJS for HTTP POST just like @PostMapping in Spring Boot.
  • @UseInterceptors()
    • The complete file uploading process and uploaded file saving process are handled here. 
    • The uploaded file will be saved in disk storage.
    • The file name will be a random string
    • The selected file will be saved in the ./csv directory
  • In uploadCsv() method, the uploaded file will be passed to AutomobileService class.

Add the business logic to save data

  • Now we can set up the service class.
  • The service class is decorated using @Injectable() decorator, this looks the same as @Service annotation in Spring Boot.
  • Since we are receiving a CSV file from the front-end, we need to store it in the database after converting it into a JSON object. 
  • I am using csvtojson library to convert CSV files into JSON.

Install cvstojson library

  • Hit the following command to install csvtojson library.
npm i --save csvtojson

  • Check csvtojson git repository for more details.

Save data using TypeORM

  • Look at the following service class

        import { Injectable } from '@nestjs/common';
        import { Vehicle } from './vehicle';
        import { InjectRepository } from '@nestjs/typeorm';
        import { Repository } from 'typeorm';

        @Injectable()
        export class AutomobileService {

        constructor(@InjectRepository(Vehicle) private vehicleRepository: Repository<Vehicle>) { }

        async saveFile(file: any): Promise<string[]> {
        const csv = require('csvtojson')
        const csvFilePath = process.cwd() + '/' + file.path;

        const vehicleArray = await csv().fromFile(csvFilePath);
        var vehicles;

        try {
        vehicles = await this.vehicleRepository.save(vehicleArray);
        } catch (error) {
        vehicles = null;
        }
         return vehicles;
        }
        }


  • You will be able to see TypeORM repository has been used to save data.
  • This repository is very similar to Repositories in Spring Data JPA.

Test your application

  • Now we all set the back-end server. I just deleted generated app.controller.spec.ts, app.controller.ts, and app.service.ts because I am not going to use them.
  • Then you can test your application, hitting the below command. 
  • The application will run on port 3000.

npm run start:dev


Enable cors

  • Before we move into the front-end part, we need to enable cors on the server-side. 
  • In NestJS very simply we can do it by adding this to main.ts file
app.enableCors();

  • Now the client application can communicate with the server.


The complete code for this article can be found at the link given below. In the next article, I will complete the front-end part. 


GIT repository





File uploading example using NestJS and Angular 11 - Part 1 File uploading example using NestJS and Angular 11 - Part 1 Reviewed by Ravi Yasas on 4:39 PM Rating: 5

No comments:

Powered by Blogger.