How to Drag and Drop File Uploading with MongoDB and Multer in Angular 8

How to Drag and Drop File Uploading with MongoDB and Multer in Angular 8

How to Drag and Drop File Uploading with MongoDB and Multer? we will learn to upload multiple image files in MongoDB database using Node and Express. In this tutorial we will create a basic Angular app in which we will create a custom directive to build Angular drag and drop functionality.

In this Angular 8 drag and drop file uploading tutorial, we will learn to upload multiple image files in MongoDB database using Node and Express. In this tutorial we will create a basic Angular app in which we will create a custom directive to build Angular drag and drop functionality.

Tutorial Objective

  • Building Angular drag and drop file uploading Layout with HTML/CSS
  • Creating a Node server to upload image files
  • Creating Custom Drag and Drop directive
  • Using Multer for Multiple file uploading
  • Multiple files uploading with progress bar

Install Angular App

Let’s start by installing basic Angular app, run the following command:

ng new angular-dragdrop-fileupload

Then, navigate to the newly created Angular project:

cd angular-dragdrop-fileupload

Next, create Angular component for drag and drop file upload.

ng g c drag-drop

Next, run command to install Bootstrap.

npm install bootstrap

Add the Bootstrap CSS in package.json file.

"styles": [

Run command to start your Angular project.

ng serve --open

Build Node/Express Server

Build a node server with express js to store the uploaded files on the MongoDB database. We will use Multer to store the image files along with other NPM packages.

Run the command from Angular project’s root to generate backend folder:

mkdir backend && cd backend

Create separate package.json for node server.

npm init

Run command to install required NPM packages.

npm install body-parser cors express mongoose multer --save

Also, install nodemon NPM module, it starts the server whenever any change occurs in server code.

npm install nodemon --save-dev

Define MongoDB Database

Create database folder inside the backend folder and also create a file backend/database/db.js in it.

module.exports = {
  db: 'mongodb://localhost:27017/meanfileupload'

Define Mongoose Schema

Create models folder inside the backend directory, then create a file User.js and place the following code inside of it.

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

// Define Schema let userSchema = new Schema({ _id: mongoose.Schema.Types.ObjectId, avatar: { type: Array }, }, { collection: 'users' })

module.exports = mongoose.model('User', userSchema)

Build File Upload REST API with Multer & Express

Let’s first create a folder and name it public inside the backend folder. Here, in this folder where we will store all the uploaded files.

Run the command from the backend folder’s root.

mkdir public

Create a routes folder inside the backend folder. Create a file user.routes.js inside of it. Here we ill import express, multer and mongoose NPM modules. By using these services we will build REST API for storing multiple files in MongoDB database.

Add the given below code inside the user.routes.js.

let express = require('express'),
  multer = require('multer'),
  mongoose = require('mongoose'),
  router = express.Router();

// Multer File upload settings const DIR = './public/';

const storage = multer.diskStorage({ destination: (req, file, cb) => { cb(null, DIR); }, filename: (req, file, cb) => { const fileName = file.originalname.toLowerCase().split(' ').join('-'); cb(null, fileName) } });

var upload = multer({ storage: storage, // limits: { // fileSize: 1024 * 1024 * 5 // }, fileFilter: (req, file, cb) => { if (file.mimetype == "image/png" || file.mimetype == "image/jpg" || file.mimetype == "image/jpeg") { cb(null, true); } else { cb(null, false); return cb(new Error('Only .png, .jpg and .jpeg format allowed!')); } } });

// User model let User = require('../models/User');'/create-user', upload.array('avatar', 6), (req, res, next) => { const reqFiles = [] const url = req.protocol + '://' + req.get('host') for (var i = 0; i < req.files.length; i++) { reqFiles.push(url + '/public/' + req.files[i].filename) }

const user = new User({ _id: new mongoose.Types.ObjectId(), avatar: reqFiles }); => { console.log(result); res.status(201).json({ message: "Done upload!", userCreated: { _id: result._id, avatar: result.avatar } }) }).catch(err => { console.log(err), res.status(500).json({ error: err }); }) })

router.get("/", (req, res, next) => { User.find().then(data => { res.status(200).json({ message: "User list retrieved successfully!", users: data }); }); });

module.exports = router;

We used Multer’s upload.array() method to upload the multiple files on the server. This method takes 2 arguments, first we pass the file name which we will be using to store the file values. Second parameter relates to the number of file we can upload at a time. Then we defined the reqFiles array here we will store the uploaded file’s path with full URL.

Configure Node/Express Server

Create server.js file inside the backend folder. Then, place the following code inside the server.js file.

let express = require('express'),
  mongoose = require('mongoose'),
  cors = require('cors'),
  bodyParser = require('body-parser'),
  dbConfig = require('./database/db');

// Routes to Handle Request const userRoute = require('../backend/routes/user.route')

// MongoDB Setup mongoose.Promise = global.Promise; mongoose.connect(dbConfig.db, { useNewUrlParser: true }).then(() => { console.log('Database sucessfully connected') }, error => { console.log('Database could not be connected: ' + error) } )

// Setup Express.js const app = express(); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: false })); app.use(cors());

// Make Images "Uploads" Folder Publicly Available app.use('/public', express.static('public'));

// API Route app.use('/api', userRoute)

const port = process.env.PORT || 4000; const server = app.listen(port, () => { console.log('Connected to port ' + port) })

// Error app.use((req, res, next) => { // Error goes via next() method setImmediate(() => { next(new Error('Something went wrong')); }); });

app.use(function (err, req, res, next) { console.error(err.message); if (!err.statusCode) err.statusCode = 500; res.status(err.statusCode).send(err.message); });

Start Node Server

Open terminal and run command to start the MongoDB server.


Then, open another terminal and run following command.

nodemon server.js

Next, you can checkout node server running on the following Url: http://localhost:4000/api

API MethodURLGET http://localhost:4000/api POST/api/create-user

You can test out Angular file uploading REST APIs Url in Postmen:

Create Angular 8 Drag and Drop File Uploading Directive

In this step, we will create HostBinding and HostListeners to manage the drag and drop functionality for Angular file upload task.

Run command to create directive in Angular project.

ng g d drag-drop-file-upload

In the drag-drop-file-upload.directive.ts file, we will define 3 HostListners such as DragoverDragleave and Drop along with HostBinding for background-color.

import { Directive, EventEmitter, Output, HostListener, HostBinding } from '@angular/core';

@Directive({ selector: '[appDragDropFileUpload]' })

export class DragDropFileUploadDirective {

@Output() fileDropped = new EventEmitter<any>();

@HostBinding('style.background-color') private background = '#ffffff';

// Dragover Event @HostListener('dragover', ['$event']) dragOver(event) { event.preventDefault(); event.stopPropagation(); this.background = '#e2eefd'; }

// Dragleave Event @HostListener('dragleave', ['$event']) public dragLeave(event) { event.preventDefault(); event.stopPropagation(); this.background = '#ffffff' }

// Drop Event @HostListener('drop', ['$event']) public drop(event) { event.preventDefault(); event.stopPropagation(); this.background = '#ffffff'; const files = event.dataTransfer.files; if (files.length > 0) { this.fileDropped.emit(files) } }


Create Angular 8 Service

We need to create Angular service, here in this file we will create a method in which we will make HTTP POST request to store the uploaded files in the mongoDB database.

Use JavaScript’s FormData() method to store the Reactive Forms value in the database via Reactive Form. To track the file upload progress define the reportProgress and observe values in Http method.

import { Injectable } from '@angular/core';
import { Observable, throwError } from 'rxjs';
import { catchError } from 'rxjs/operators';
import { HttpErrorResponse, HttpClient } from '@angular/common/http';

@Injectable({ providedIn: 'root' })

export class DragdropService {

constructor(private http: HttpClient) { }

addFiles(images: File) { var arr = [] var formData = new FormData(); arr.push(images);

arr[0].forEach((item, i) =&gt; {
  formData.append('avatar', arr[0][i]);

return'http://localhost:4000/api/create-user', formData, {
  reportProgress: true,
  observe: 'events'


errorMgmt(error: HttpErrorResponse) { let errorMessage = ''; if (error.error instanceof ErrorEvent) { // Get client-side error errorMessage = error.error.message; } else { // Get server-side error errorMessage = Error Code: ${error.status}\nMessage: ${error.message}; } console.log(errorMessage); return throwError(errorMessage); }


Create Drag and Drop File Upload Component

Now, we will create the layout for drag and drop file upload component. In this tutorial we will be using Reactive Forms to store the files and Node server to store the files into the mongoDB database.

Import ReactiveFormsModule in app.module.ts file to enable the service.

import { ReactiveFormsModule } from '@angular/forms';

@NgModule({ declarations: [...], imports: [ ReactiveFormsModule ], bootstrap: [...] })

export class AppModule { }

Next, add the code inside the app/drag-drop.component.html file.

<div class="container fileUploadWrapper">
    <form [formGroup]="form">
        <div class="row">
            <!-- Progress Bar -->
            <div class="col-md-12" *ngIf="progress">
                <div class="progress form-group">
                    <div class="progress-bar progress-bar-striped bg-success" role="progressbar"

        &lt;div class="col-md-12"&gt;
            &lt;div class="fileupload" appDragDropFileUpload (click)=""
                &lt;span class="ddinfo"&gt;Choose a file or drag here&lt;/span&gt;
                &lt;input type="file" name="avatars" #fileField (change)="upload($" hidden multiple&gt;

        &lt;div class="col-md-12"&gt;
            &lt;div class="image-list" *ngFor="let file of fileArr; let i = index"&gt;
                &lt;div class="profile"&gt;
                    &lt;img [src]="sanitize(file['url'])" alt=""&gt;
            &lt;p class="message"&gt;{{msg}}&lt;/p&gt;


Apply design to Angular drag and drop file uploading component, navigate to styles.css and paste the following code.

* {
    box-sizing: border-box;

body { margin: 0; padding: 25px 0 0 0; background: #291464; }

.container { margin-top: 30px; max-width: 500px; }

.progress { margin-bottom: 30px; }

.fileupload { background-image: url("./assets/upload-icon.png"); background-repeat: no-repeat; background-size: 100px; background-position: center; background-color: #ffffff; height: 200px; width: 100%; cursor: pointer; /* border: 2px dashed #0f68ff; */ border-radius: 6px; margin-bottom: 25px; background-position: center 28px; }

.ddinfo { display: block; text-align: center; padding-top: 130px; color: #a0a1a2; }

.image-list { display: flex; width: 100%; background: #C2DFFC; border: 1px solid; border-radius: 3px; padding: 10px 10px 10px 15px; margin-bottom: 10px; }

.image-list p { line-height: normal; padding: 0; margin: 0 0 0 14px; display: inline-block; position: relative; top: -2px; color: #150938; font-size: 14px; }

.message { text-align: center; color: #C2DFFC; }

.remove { background: transparent; border: none; cursor: pointer; }

.profile { width: 40px; height: 40px; overflow: hidden; border-radius: 4px; display: inline-block; }

.profile img { width: 100%; }

.remove img { width: 15px; position: relative; top: -2px; }

.fileUploadWrapper .card-body { max-height: 330px; overflow: hidden; overflow-y: auto; }

@media(max-width: 767px) { .container { width: 280px; margin: 20px auto 100px; } }

Paste the following code in app/drag-drop.component.ts file:

import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, FormArray } from "@angular/forms";
import { DragdropService } from "../dragdrop.service";
import { HttpEvent, HttpEventType } from '@angular/common/http';
import { DomSanitizer } from '@angular/platform-browser';

@Component({ selector: 'app-drag-drop', templateUrl: './drag-drop.component.html', styleUrls: ['./drag-drop.component.css'] })

export class DragDropComponent implements OnInit {

fileArr = []; imgArr = []; fileObj = []; form: FormGroup; msg: string; progress: number = 0;

constructor( public fb: FormBuilder, private sanitizer: DomSanitizer, public dragdropService: DragdropService ) { this.form ={ avatar: [null] }) }

ngOnInit() { }

upload(e) { const fileListAsArray = Array.from(e); fileListAsArray.forEach((item, i) => { const file = (e as HTMLInputElement); const url = URL.createObjectURL(file[i]); this.imgArr.push(url); this.fileArr.push({ item, url: url }); })

this.fileArr.forEach((item) =&gt; {

// Set files form control
  avatar: this.fileObj


// Upload to server
  .subscribe((event: HttpEvent&lt;any&gt;) =&gt; {
    switch (event.type) {
      case HttpEventType.Sent:
        console.log('Request has been made!');
      case HttpEventType.ResponseHeader:
        console.log('Response header has been received!');
      case HttpEventType.UploadProgress:
        this.progress = Math.round(event.loaded / * 100);
        console.log(`Uploaded! ${this.progress}%`);
      case HttpEventType.Response:
        console.log('File uploaded successfully!', event.body);
        setTimeout(() =&gt; {
          this.progress = 0;
          this.fileArr = [];
          this.fileObj = [];
          this.msg = "File uploaded successfully!"
        }, 3000);


// Clean Url sanitize(url: string) { return this.sanitizer.bypassSecurityTrustUrl(url); }



Finally, Angular 8 Drag and Drop multiple files uploading tutorial with MongoDB & Multer is over.

I hope this tutorial will surely help and you if you liked this tutorial, please consider sharing it with others.

This post was originally published here

angular angular-js mongodb node-js express

Bootstrap 5 Complete Course with Examples

Bootstrap 5 Tutorial - Bootstrap 5 Crash Course for Beginners

Nest.JS Tutorial for Beginners

Hello Vue 3: A First Look at Vue 3 and the Composition API

Building a simple Applications with Vue 3

Deno Crash Course: Explore Deno and Create a full REST API with Deno

How to Build a Real-time Chat App with Deno and WebSockets

Convert HTML to Markdown Online

HTML entity encoder decoder Online

Node.js Express MongoDB Tutorial

Node.js Express MongoDB Tutorial is CRUD example, I have created to showcase Express web framework, MongoDB NoSQL database, and Node.js server platform.

How to Use Express.js, Node.js and MongoDB.js

In this post, I will show you how to use Express.js, Node.js and MongoDB.js. We will be creating a very simple Node application, that will allow users to input data that they want to store in a MongoDB database. It will also show all items that have been entered into the database.

Ecommerce MERN(MongoDB Express.js React.js Node.js) Redux Tailwind

Ecommerce MERN(MongoDB Express.js React.js Node.js) Redux Tailwind

Создание сайта на Mongo DB, Express JS, Node JS и Angular

Видео курс по изучению стека MEAN. В курсе вы научитесь создавать сайты при помощи Node JS, Express JS, Angular JS и баз данных MongoDB. Вы ознакомитесь со всеми моментами разработки и в конце курса выгрузите сайт на удаленный сервер.

Angular 8 Node & Express JS File Upload

In this Angular 8 and Node.js tutorial, we are going to look at how to upload files on the Node server. To create Angular image upload component, we will be using Angular 8 front-end framework along with ng2-file-upload NPM package; It’s an easy to use Angular directives for uploading the files.