March 13, 2019

Implementing File Upload Using Node and Angular

by Jay Raj

Implementing File Upload Using Node and Angular

In this tutorial, you'll learn how to implement file upload using Angular and Node.js. Using Express Node, you'll create the file upload request handler which will upload the file to the server. You'll implement the file upload user interface using Angular.

The source code from this tutorial is available on GitHub.

Creating the Angular App

To get started with this tutorial, you'll need to install the Angular CLI in your system. Let's get started with installing the Angular CLI using Node Package Manager (npm).

npm install -g @angular/cli

Once you have installed the Angular CLI, create an Angular app using the command line tool.

ng new angular-file-upload

The above command will create the Angular project boilerplate. Navigate to the project directory and start the Angular app.

cd angular-file-upload
npm start

Point your browser to http://localhost:4200 and you will have the default application running.

Creating the File Upload UI

The default Angular boilerplate code creates an Angular component called AppComponent in the src/app/ folder. A component has an HTML file, a controller file, and a CSS file.
Remove the HTML code from the src/app/app.component.html and add the following code:

<div class="mainContainer">
    <div class="content">
        <div class="header">
            <h1>Angular File Upload</h1>
        </div>
        <div class="row margin25">

            <div class="col-md-4">

            </div>
            <div class="col-md-4">
                <div class="input-group">
                    <div class="input-group-prepend">
                        <span class="input-group-text upload" id="btnUpload">Upload</span>
                    </div>
                    <div class="custom-file">
                        <form action="/api/upload" method="post" enctype="multipart/form-data">
                            <input type="file" class="custom-file-input" id="inputGroupFile01" aria-describedby="inputGroupFileAddon01">
                        </form>
                        <label class="custom-file-label" for="inputGroupFile01">Choose file</label>
                    </div>
                </div>
            </div>
            <div class="col-md-4">

            </div>
        </div>
    </div>
</div>

Add the following CSS style to the src/app/app.component.css file.

.header {
    text-align: center;
}

.header h1 {
    font-family: serif;
    font-size: 38px;
    font-family: 'Times New Roman';
}

.content {
    margin: 100px;
}

.margin25 {
    margin: 25px;
}

.upload {
    cursor: pointer;
}

You'll be using bootstrap for styling up the Angular user interface. So, install bootstrap using npm inside the Angular project.

npm install --save bootstrap

Once you have installed bootstrap, include the Bootstrap style inside the angular.json file under the build configurations.

"styles": [
  "src/styles.css",
  "node_modules/bootstrap/dist/css/bootstrap.min.css"
]

Save the application and you will be able to see the Angular user interface for file upload.

Angular File Upload UI

Creating the Node.js File Upload Handler

You need a file upload handler to handle the request sent from the Angular application. You'll be making use of the Express framework for creating the Node handler.

Create a folder called file-upload-server and initialize the Node project inside it.

mkdir file-upload-folder
cd file-upload-folder
npm init

Once you have the Node project initialized, install the express framework using npm.

npm install --save express

Create a file called app.js inside the project folder. You'll be making use of body-parser to parse the post parameter to the request handler. Install it now:

npm install --save body-parser

You'll also be using the connect-multiparty module to upload the file.

npm install --save connect-multiparty

Once you have the required dependencies for writing the file upload handler, let's start by creating the Express app. Add the following code to the app.js file:

const  express  =  require('express')
const  app  =  express()
const  port  =  3000

app.get('/api/upload', (req, res) => {
    res.json({
        'message': 'hello'
    });
});

app.listen(port, () => console.log(`Example app listening on port ${port}!`))

As seen in the above code, you created the Express app using the express module. After creating the app, you defined the Express route /api/upload which returns a JSON message.

Save the above changes and start the Express app.

node app.js

Point your browser to http://localhost:3000/api/upload and you will have the JSON response rendered in the browser.

For writing the file upload request handler, you'll need a route which handles POST requests. So, modify the existing route to a POST route.

You'll be using the connect-multiparty module to handle file upload, so require the module and define the file upload folder. Make sure to create a folder called uploads inside the project directory.

const  multipart  =  require('connect-multiparty');
const  multipartMiddleware  =  multipart({ uploadDir:  './uploads' });

Add the connect-mutiparty middleware to the POST file upload route.

app.post('/api/upload', multipartMiddleware, (req, res) => {
    res.json({
        'message': 'File uploaded successfully'
    });
});

In order to parse the file upload request posted to the file handler route, you need to make use of the body-parser module. So, require the body-parser module and use it across the application.

const bodyParser = require("body-parser");
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
    extended: true
}));

Here is how the app.js file looks:

const express = require('express')
const app = express()
const port = 3000
const bodyParser = require("body-parser");
const multipart = require('connect-multiparty');
const multipartMiddleware = multipart({
    uploadDir: './uploads'
});

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
    extended: true
}));

app.post('/api/upload', multipartMiddleware, (req, res) => {
    res.json({
        'message': 'File uploaded succesfully.'
    });
});

app.listen(port, () => console.log(`Example app listening on port ${port}!`))

Save the changes and run the node app.

node app.js

You will have the Express app running at http://localhost:3000.

File Upload From Angular

To route the file upload requests from Angular to the Node server, you need to set a proxy inside the Angular app. In the Angular app directory, create a proxy.conf.json file and add the following code to set a proxy to the node server.

{
    "/api/*": {
        "target": "http://localhost:3000/", "secure": false
    }
}

From the package.json file, modify the start script to serve the Angular app using the proxy.

ng serve --proxy-config proxy.conf.json

Now, add a file change event to the input type file element inside the app.component.html file.

<input  (change)="fileChange($event)"  type="file"  class="custom-file-input"  id="inputGroupFile01"  aria-describedby="inputGroupFileAddon01">

Define the fileChange method inside the app.component.ts file.

  fileChange(element) {
      this.uploadedFiles = element.target.files;
  }

On file change, the uploadedFiles array gets updated with uploaded files which can be posted to the file upload route on button click. Add the upload click event to the Upload button.

<span  class="input-group-text upload"  (click)="upload()"  id="btnUpload">Upload</span>

Define the upload method inside the app.component.ts file.

upload() {
    let formData = new FormData();
    for (var i = 0; i < this.uploadedFiles.length; i++) {
        formData.append("uploads[]", this.uploadedFiles[i], this.uploadedFiles[i].name);
    }
    this.http.post('/api/upload', formData)
    .subscribe((response) => {
         console.log('response received is ', response);
    })
}

Iterating the uploadedFiles array, you create the formData and POST it to the Express file handler /api/upload.

Here is how the app.component.ts file looks:

import { Component, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {

    uploadedFiles: Array < File > ;

    constructor(private http: HttpClient) {

    }

    ngOnInit() {

    }

    fileChange(element) {
        this.uploadedFiles = element.target.files;
    }

    upload() {
        let formData = new FormData();
        for (var i = 0; i < this.uploadedFiles.length; i++) {
            formData.append("uploads[]", this.uploadedFiles[i], this.uploadedFiles[i].name);
        }
        this.http.post('/api/upload', formData)
            .subscribe((response) => {
                console.log('response received is ', response);
            })
    }

}

Protect your Angular App with Jscrambler

Save the above changes and browse a file and click the upload button. On successful file upload, a success message will be logged in the browser console.

You can find the uploaded file in the uploads folder inside the Node server app.

Conclusion

In this tutorial, you learned how to implement file upload using Angular and Node.js. You used the Express framework for writing the file upload handler.

Also, if you're building Angular applications with sensitive logic, be sure to protect them against code theft and reverse-engineering by following our guide.