Angular 5 File Upload Drag and Drop
Angular thirteen drag and drop file upload tutorial; In this article; nosotros will acquire to upload multiple image files in MongoDB database using Node and Limited.
In this tutorial we will create a basic Angular app in which we volition use to create a custom directive to build Angular drag and drop functionality.
Tutorial Objective
- Building Angular elevate and drop file uploading Layout with HTML/CSS
- Creating a Node server to upload image files
- Creating Custom Drag and Driblet directive
- Using Multer for Multiple file uploading
- Multiple files uploading with progress bar
Athwart thirteen Elevate and Driblet File Uploading Example
- Install Athwart App
- Build Node/Limited Server
- Build File Upload Balance API with Multer & Express
- Configure Node/Express Server
- Create Angular Drag and Drib File Uploading Directive
- Create Angular Service
- Create Elevate and Drop File Upload Component
Install Angular App
Let's start by installing basic Angular app, run the post-obit command:
ng new athwart-dragdrop-fileupload
Then, navigate to the newly created Angular projection:
cd angular-dragdrop-fileupload
Next, create Angular component for drag and driblet 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" : [ "node_modules/bootstrap/dist/css/bootstrap.min.css" , "src/styles.scss" ]
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 shop the image files along with other NPM packages.
Run the command from Athwart project'south root to generate backend folder:
mkdir backend && cd backend
Create dissever package.json
for node server.
npm init
Run control to install required NPM packages.
npm install body-parser cors express mongoose multer --salvage
As well, install nodemon NPM module, information technology starts the server whenever any change occurs in server code.
npm install nodemon --save-dev
Define Mongoose Schema
Create models folder inside the backend directory, then create a file User.js
and place the following code within 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 Residuum API with Multer & Limited
Let'due south 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 control from the backend folder's root.
mkdir public
Create a routes folder inside the backend binder. Create a file user.routes.js inside of it. Hither we ill import express, multer and mongoose NPM modules. Past using these services we will build Balance API for storing multiple files in MongoDB database.
Add the given beneath lawmaking inside the user.routes.js
.
let express = require ( 'limited' ) , 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 * v // }, fileFilter : ( req, file, cb ) => { if (file.mimetype == "image/png" || file.mimetype == "image/jpg" || file.mimetype == "image/jpeg" ) { cb ( zip , true ) ; } else { cb ( null , fake ) ; return cb ( new Error ( 'Just .png, .jpg and .jpeg format allowed!' ) ) ; } } } ) ; // User model allow User = require ( '../models/User' ) ; router. post ( '/create-user' , upload. assortment ( 'avatar' , vi ) , ( req, res, next ) => { const reqFiles = [ ] const url = req.protocol + '://' + req. go ( '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 } ) ; user. save ( ) . then ( issue => { console. log (consequence) ; res. status ( 201 ) . json ( { message: "Done upload!" , userCreated: { _id: result._id, avatar: result.avatar } } ) } ) . grab ( err => { console. log (err) , res. status ( 500 ) . json ( { mistake: err } ) ; } ) } ) router. go ( "/" , ( req, res, next ) => { User. find ( ) . so ( 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 ii arguments, start we pass the file name which we will be using to store the file values. Second parameter relates to the number of file nosotros can upload at a time. So we defined the reqFiles array here we will store the uploaded file's path with total URL.
Configure Node/Express Server
Create server.js file inside the backend binder. Then, identify the post-obit code inside the server.js
file.
const express = require ( 'express' ) const mongoose = require ( 'mongoose' ) const cors = require ( 'cors' ) const bodyParser = crave ( 'body-parser' ) // Routes to Handle Request const userRoute = require ( './routes/user.routes' ) // MongoDB Setup mongoose . connect ( 'mongodb://127.0.0.i:27017/mydatabase' ) . and so ( ( x ) => { panel. log ( ` Connected to Mongo! Database name: " ${ten.connections[ 0 ] .name} " ` ) } ) . catch ( ( err ) => { console. error ( 'Fault connecting to mongo' , err.reason) } ) // Setup Limited.js const app = express ( ) app. use (bodyParser. json ( ) ) app. utilize ( bodyParser. urlencoded ( { extended : false , } ) , ) app. apply ( cors ( ) ) // Make Images "Uploads" Binder Publicly Bachelor app. use ( '/public' , limited. 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, adjacent ) => { // Fault goes via `next()` method setImmediate ( ( ) => { adjacent ( new Mistake ( 'Something went wrong' ) ) } ) } ) app. utilize ( office ( err, req, res, side by side ) { console. error (err.message) if ( !err.statusCode) err.statusCode = 500 res. status (err.statusCode) . send (err.message) } )
Open the backend/package.json file and change main from index.js to server.js.
{ ... ... "main" : "server.js" , ... ... }
Start Node Server
Open up concluding and run command to start the MongoDB server.
mongod
Then, open another final and run following control.
nodemon server.js
Side by side, you can checkout node server running on the following Url: http://localhost:4000/api
API Method | URL |
---|---|
Get | http://localhost:4000/api |
Mail service | /api/create-user |
You can test out Angular file uploading Remainder APIs Url in Postmen:
Create Angular Drag and Drop File Uploading Directive
In this step, we will create HostBinding and HostListeners to manage the drag and drop functionality for Athwart file upload task.
Run control to create directive in Angular projection.
ng chiliad d drag-drop-file-upload
In the drag-drop-file-upload.directive.ts
file, nosotros will define iii HostListners such as Dragover, Dragleave and Drop forth with HostBinding for background-colour.
import { Directive, EventEmitter, Output, HostListener, HostBinding, } from '@athwart/core' ; @Directive ( { selector : '[appDragDropFileUpload]' , } ) export class DragDropFileUploadDirective { @Output ( ) fileDropped = new EventEmitter <whatsoever> ( ) ; @HostBinding ( 'fashion.background-colour' ) individual background = '#ffffff' ; // Dragover Event @HostListener ( 'dragover' , [ '$event' ] ) dragOver ( event : whatever ) { event. preventDefault ( ) ; event. stopPropagation ( ) ; this .background = '#e2eefd' ; } // Dragleave Event @HostListener ( 'dragleave' , [ '$event' ] ) public dragLeave ( event : any ) { effect. preventDefault ( ) ; event. stopPropagation ( ) ; this .groundwork = '#ffffff' ; } // Driblet Event @HostListener ( 'drop' , [ '$event' ] ) public driblet ( event : whatever ) { issue. preventDefault ( ) ; event. stopPropagation ( ) ; this .background = '#ffffff' ; const files = event.dataTransfer.files; if (files.length > 0 ) { this .fileDropped. emit (files) ; } } }
Create Angular 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 Course. To track the file upload progress define the reportProgress and notice values in Http method.
Outset, create service file using given command in angular projection.
ng 1000 s drag-drop
Next, open the src/app/elevate-drib.service.ts file.
import { Injectable } from '@angular/core' ; import { Appreciable, throwError } from 'rxjs' ; import { catchError } from 'rxjs/operators' ; import { HttpErrorResponse, HttpClient } from '@angular/mutual/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((particular, i) => { formData.suspend ( 'avatar' , arr[0][i]) ; } ) return this.http.post('http://localhost:4000/api/create-user', formData, { reportProgress : true, observe : 'events' } ).pipe ( catchError (this.errorMgmt) ) } errorMgmt(error: HttpErrorResponse) { permit errorMessage = '' ; if (fault.error instanceof ErrorEvent) { // Get client-side error errorMessage = mistake.error.message; } else { // Get server-side error errorMessage = `Error Lawmaking: $ {error.condition} \nMessage: $ {mistake.message}`; } console.log (errorMessage) ; return throwError (errorMessage) ; } }
Create Drag and Drop File Upload Component
Now, nosotros will create the layout for elevate and drop file upload component. In this tutorial nosotros will exist using Reactive Forms to shop the files and Node server to shop the files into the mongoDB database.
Import ReactiveFormsModule and HttpClientModule in app.module.ts
file to enable the service.
import { ReactiveFormsModule } from '@athwart/forms' ; import {HttpClientModule} from '@angular/common/http' ; @ NgModule ( { declarations: [ ... ] , imports: [ ReactiveFormsModule, HttpClientModule ] , bootstrap: [ ... ] } ) export course AppModule { }
Next, add the code inside the app/drag-drop.component.html
file.
<div class = "container fileUploadWrapper" > <grade [formGroup] = "form" > <div class = "row" > <!-- Progress Bar --> <div class = "col-md-12" *ngIf = "progress" > <div class = "progress course-group" > <div class = "progress-bar progress-bar-striped bg-success" function = "progressbar" [fashion.width.%] = "progress" > </div > </div > </div > <div class = "col-doctor-12" > <div form = "fileupload" appDragDropFileUpload (click) = "fileField.click()" (fileDropped) = "upload($event)" > <span class = "ddinfo" > Choose a file or drag here </span > <input type = "file" proper noun = "avatars" #fileField (modify) = "upload($any($event).target.files)" hidden multiple /> </div > </div > <div class = "col-dr.-12" > <div class = "image-list" *ngFor = "permit file of fileArr; permit i = alphabetize" > <div class = "contour" > <img [src] = "sanitize(file['url'])" alt = " " /> </div > <p > {{ file.item.name }} </p > </div > <p class = "message" > {{ msg }} </p > </div > </div > </form > </div >
Apply pattern 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 { groundwork-image : url ("./assets/upload-icon.png") ; groundwork-echo : no-repeat; background-size : 100px; background-position : center; background-color : #ffffff; top : 200px; width : 100%; cursor : pointer; /* border: 2px dashed #0f68ff; */ edge-radius : 6px; margin-lesser : 25px; background-position : centre 28px; } .ddinfo { brandish : 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; } .epitome-list p { line-elevation : normal; padding : 0; margin : 0 0 0 14px; display : inline-block; position : relative; top : -2px; colour : #150938; font-size : 14px; } .message { text-marshal : eye; color : #C2DFFC; } .remove { background : transparent; edge : none; cursor : pointer; } .profile { width : 40px; summit : 40px; overflow : subconscious; edge-radius : 4px; display : inline-cake; } .profile img { width : 100%; } .remove img { width : 15px; position : relative; superlative : -2px; } .fileUploadWrapper .carte du jour-body { max-top : 330px; overflow : subconscious; overflow-y : automobile; } @media ( max-width : 767px) { .container { width : 280px; margin : 20px auto 100px; } }
in order to remove strict blazon check warning in typescript set "strict": false nether compilerOptions in tsconfig.json file.
Paste the following lawmaking in app/elevate-driblet.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 '@athwart/common/http' ; import { DomSanitizer } from '@athwart/platform-browser' ; @Component ( { selector: 'app-drag-drop' , templateUrl: './drag-drib.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 .class = this .fb. group ( { avatar: [ goose egg ] } ) } ngOnInit ( ) { } upload ( east ) { const fileListAsArray = Array . from (e) ; fileListAsArray. forEach ( ( detail, i ) => { const file = (eastward as HTMLInputElement) ; const url = URL . createObjectURL (file[i] ) ; this .imgArr. push (url) ; this .fileArr. push button ( { item, url: url } ) ; } ) this .fileArr. forEach ( ( particular ) => { this .fileObj. push (detail.item) } ) // Set up files class control this .form. patchValue ( { avatar: this .fileObj } ) this .form. get ( 'avatar' ) . updateValueAndValidity ( ) // Upload to server this .dragdropService. addFiles ( this .form.value.avatar) . subscribe ( ( upshot: HttpEvent< whatever > ) => { switch (event. type ) { case HttpEventType.Sent: panel . log ( 'Request has been fabricated!' ) ; break ; case HttpEventType.ResponseHeader: console . log ( 'Response header has been received!' ) ; suspension ; case HttpEventType.UploadProgress: this .progress = Math. round (result.loaded / consequence.total * 100 ) ; console . log ( ` Uploaded! ${ this .progress} % ` ) ; break ; instance HttpEventType.Response: console . log ( 'File uploaded successfully!' , result.body) ; setTimeout ( ( ) => { this .progress = 0 ; this .fileArr = [ ] ; this .fileObj = [ ] ; this .msg = "File uploaded successfully!" } , 3000 ) ; } } ) } // Clean Url sanitize ( url: cord ) { return this .sanitizer. bypassSecurityTrustUrl (url) ; } }
Adjacent, become to app.component.html file and remove the electric current lawmaking and add the given component tag into it.
<app-elevate-drib > </app-elevate-drib >
Run command to start your Angular project.
ng serve --open
Decision
Finally, Angular Drag and Drib multiple files uploading tutorial with MongoDB & Multer is completed. You can employ the given link to download the sample projection.
Git Repo
Recommended Posts:
Source: https://www.positronx.io/angular-drag-and-drop-file-uploading-with-mongodb-multer/
0 Response to "Angular 5 File Upload Drag and Drop"
Post a Comment