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:

Angular Drag and Drop File UploadA

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