Angular 10/9 Upload Image using Node.js Server APIs built on Express Js

Hey there! in this post, we are going to learn how to upload images and documents using post HTTP calls with a Node.js server. We’ll be creating the API routes using Express.js and use the Multer package module for tasks related to file uploading.

We have a lot to learn in this post, we’ll set up a Node.js based server, install some required and life easing package modules like Cors and FileExtension.

At the client-side, you can use any framework or can have a simple HTML form. But here we are using an Angular app with a form to upload files to the server. The Form we use Reactive approach to submit the selected file to the server.

For beautifying our application we will just add the bootstrap.css library.

Before we go ahead let’s have a look at the star castings …

 

What is Node.js why it is used?

Node.js is an open-source, cross-platform, JavaScript runtime environment based on Chrome’s V8 engine (fastest of all times) that executes JavaScript code outside of a web browser. Basically we use Javascript at server-side code with the help on Node.js. There is number of packages available to do almost anything.

  • It is used and accepted as a standard for developing many enterprise-level applications. Check some of the reasons:
  • It helps in creating real-time apps like games and social chats which is lightning fast.
  • Developers known to Javascript efficiently work on front and back-ends.
  • A large storehouse of NPM packages for any type needs to boost productivity.
  • It is quicker than any other language.

 

What is ExpressJs?

Express.js, or simply Express, is a web application framework for Node.js, released as free and open-source software under the MIT License. It is designed for building web applications and APIs. It has been called the de facto standard server framework for Node.js.

 

How Multer Works?

We are using Multer here as an Express middleware. A middleware is a piece of code that is executed before some other software components. In Express, middleware is used to process and transform the coming requests to the server. Multer is helping us while uploading files to the Node.js server.

 

Let’s get started!

 

Create a Server Directory

We are going to create a local server using Node.js, which you can later upload on a real-server for production-level applications.

Execute the following commands to create a directory upload-server with a file server.js in it.

# Make directory
$ mkdir upload-server

# Move inside
$ cd  upload-server

# Create server.js file
$ type nul > server.js

 

Directory to Save Uploaded Files

Also, create a directory upload-server > my_uploaded_files folder to save the files upload from the client-side by the users.

# Save uploaded files 
mkdir my_uploaded_files

 

Install Required NPM Packages

Now, we’ll install the npm packages for our Node.js. For obvious make sure you have the latest version of Node.js installed.

Run following npm command to install express, multer, cors, and file-extension package to use in the server.js

$ npm install --save express multer cors file-extension

Prepare Node.js Server

Our server is the upload-server > server.js file, update it with following code

// call all the required packages
const express = require('express')
const multer = require('multer');
var cors = require('cors');
var fileExtension = require('file-extension')

//CREATE EXPRESS APP
const app = express();

// cors allow usage of server from different origin only for development
app.use(cors())


//ROUTES WILL GO HERE
app.get('/', function (req, res) {
    res.json({ message: 'Server Started!' });
});

app.listen(3000, () => console.log('Server started on port 3000'));

In the above code, we have initialized the required modules, defined a base API route using express get() method. Our server will be started at defined port number which is 300 here.

 

Update the Server to Save Uploaded Files

Let’s move forward and make changes to create out API using the Express route and save uploaded files in the folder using Multer.

 

Multer Middleware Configuration

Multer plays an important role in easing out the operations we used to spend a lot of time. We can configure it according to our needs. Let’s discuss further steps.

 

Define Storage Destination & Filename

To define the destination folder directory and name of the file which will be saved in that directory, we use the diskStorage method available in the multer

// Configure Storage
var storage = multer.diskStorage({

    // Setting directory on disk to save uploaded files
    destination: function (req, file, cb) {
        cb(null, 'my_uploaded_files')
    },

    // Setting name of file saved
    filename: function (req, file, cb) {
        cb(null, file.fieldname + '-' + Date.now() + '.' + fileExtension(file.originalname))
    }
})

The destination property takes a function to its callback method defining directory name which is 'my_uploaded_files' in our case.

The filename property also returns a function to set the name of the file to be saved. We have also used the fileExtension to get an extension of the original file name.

Next, we will assign the storage object to multer‘s storage property.

 

Add File Extension Filters & Size Limits in Multer

Multer as a middleware allows us to apply validations for file size and its type. Multer allows us to configure the limit of the size in bytes of the files being uploaded.

var upload = multer({
    storage: storage,
    limits: {
        // Setting Image Size Limit to 2MBs
        fileSize: 2000000
    },
    fileFilter(req, file, cb) {
        if (!file.originalname.match(/\.(jpg|jpeg|png)$/)) {
            //Error 
            cb(new Error('Please upload JPG and PNG images only!'))
        }
        //Success 
        cb(undefined, true)
    }
})

In the fileFilter method, we have returned callbacks (cb)  the allowed file extension does not match with regex provided. Currently, it will only allow Images but you can change it to any extension type.

 

Add Upload Express API Route

Finally, we’ll add the '/uploadFile' route using Express post() method which accepts multer object upload for single file.

app.post('/uploadfile', upload.single('uploadedImage'), (req, res, next) => {
    const file = req.file
    console.log(req);
    if (!file) {
        const error = new Error('Please upload a file')
        error.httpStatusCode = 400
        return next(error)
    }
    res.status(200).send({
        statusCode: 200,
        status: 'success',
        uploadedFile: file
    })

}, (error, req, res, next) => {
    res.status(400).send({
        error: error.message
    })
})

That’s it we are done on the server-side. In the next step Run Node.js server to use /uploadFile API in our Angular App.

 

Run Node.js Server

To run the Node.js server run node server.js command with root set on upload-server

$ upload-server>node server.js
Server started on port 3000

It will start the server at http://localhost:3000/ with the route set to root and print the message ‘Server Started!

 

Create an Angular Application

Now we will create a sample Angular application with a Reactive Form to upload files.

Setup Angular Project

Execute following command to create a new Angular project using Angular CLI

$ ng new angular-upload-file-using-nodejs

Move to the project folder

$ cd angular-upload-file-using-nodejs

 

Add Bootstrap

To style the app, include bootstrap.css file in the Index.html file’s <head> section

<head>
  ...
  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css">
</head>

 

Update App Module

Now, import the FormModule and HttpClientModule in the app.module.ts file

// app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';

import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    ReactiveFormsModule,
    HttpClientModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

 

Update App Component

Next, update the App component’s HTML template and class file to add the form

App Template

Add form element with [formGroup] and (ngSubmit) with a file input control. Open the app.component.html file and place following code in it

<div class="container">
  <h3>Upload File</h3>


  <form [formGroup]="fileUploadForm" (ngSubmit)="onFormSubmit()">
    <div class="row">
      <div class="col-sm-12">
        <div>
          <h6 class="head-title margin-top-8"><span>Select Image File</span></h6>
        </div>
      </div>
      <div class="col-sm-6">

        <div class="custom-file">

          <input type="file" class="custom-file-input" id="customFile" name="uploadedImage"
            (change)="onFileSelect($event)" #UploadFileInput>

          <label class="custom-file-label" for="customFile">{{fileInputLabel || 'Choose File'}}</label>
        
        </div>

      </div>

      <div class="col-sm-6"> <button class="btn btn-primary" type="submit">Upload</button> </div>

    </div>
  </form>

</div>

Update Component Class

In the class component, we will make an HTTP post call using the HttpClient method to post the selected image on the Nodejs server.

// app.component.ts
import { Component, ViewChild, ElementRef } from '@angular/core';
import { FormGroup, FormBuilder } from '@angular/forms';
import { HttpClient } from '@angular/common/http';
import * as _ from 'lodash';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {
  title = 'angular-image-file-upload-tutorial';

  @ViewChild('UploadFileInput', { static: false }) uploadFileInput: ElementRef;
  fileUploadForm: FormGroup;
  fileInputLabel: string;

  constructor(
    private http: HttpClient,
    private formBuilder: FormBuilder
  ) { }

  ngOnInit(): void {
    this.fileUploadForm = this.formBuilder.group({
      uploadedImage: ['']
    });
  }

  onFileSelect(event) {
    const file = event.target.files[0];
    this.fileInputLabel = file.name;
    this.fileUploadForm.get('uploadedImage').setValue(file);
  }


  onFormSubmit() {

    if (!this.fileUploadForm.get('uploadedImage').value) {
      alert('Please fill valid details!');
      return false;
    }

    const formData = new FormData();
    formData.append('uploadedImage', this.fileUploadForm.get('uploadedImage').value);
    formData.append('agentId', '007');


    this.http
      .post<any>('http://localhost:3000/uploadfile', formData).subscribe(response => {
        console.log(response);
        if (response.statusCode === 200) {
          // Reset the file input
          this.uploadFileInput.nativeElement.value = "";
          this.fileInputLabel = undefined;
        }
      }, er => {
        console.log(er);
        alert(er.error.error);
      });
  }


}

 

Run Client-Side Angular Project

That’s it we are done with both NodeJs server and Client-side Angular app to test. make sure to run both of them by executing below command:

Run Application

$ ng serve --o

Run Node.js Server

>node server.js
Server started on port 3000

 

Conclusion

That’s it from my side, we learned many new things during this tutorial. We created a Nodejs server using Express to build Upload File API and use the Multer module to easily implement file upload functions. We also use File Extention and CORS plugin to resolve common problems.

Hope you enjoyed this tutorial. Please share it with others 🙂

Thanks for Reading!

Leave a Reply

Your email address will not be published. Required fields are marked *