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.
[lwptoc]
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 <code class="language-batch">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