Angular 9/10 Drag and Drop Multiple Files Upload to Firebase Storage Using AngularFire2 Full Project

You are currently viewing Angular 9/10 Drag and Drop Multiple Files Upload to Firebase Storage Using AngularFire2 Full Project

Welcome folks today in this post we will talk about how to upload multiple files to firebase storage using angularfire2 full project in angular 9/10. All the source code is given below in the blog. A step by step youtube video is also shown below.

 

 

Screenshots

 

 

Import Dependencies

 

import { AngularFirestore } from '@angular/fire/firestore';
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import {HttpClientModule} from '@angular/common/http';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import {AngularFireStorageModule} from '@angular/fire/storage'
import {AngularFireModule} from '@angular/fire';
import { DropzoneDirective } from './dropzone.directive';
import { UploaderComponent } from './uploader/uploader.component';
import { UploadTaskComponent } from './upload-task/upload-task.component'
@NgModule({
  declarations: [
    AppComponent,
    DropzoneDirective,
    UploaderComponent,
    UploadTaskComponent,

  
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    HttpClientModule,
    BrowserAnimationsModule,
    AngularFireModule.initializeApp({
      apiKey: "",
    authDomain: "",
    databaseURL: "",
    projectId: "",
    storageBucket: "",
    messagingSenderId: "",
    appId: ""
    }),
    AngularFireStorageModule
  
  
  ],
  providers: [AngularFirestore],
  bootstrap: [AppComponent]
})
export class AppModule { }

 

/* You can add global styles to this file, and also import other style files */



.dropzone {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-direction: column;
    min-width: 80vw;
    font-weight: 200;
    height: 300px;
    border: 2px dashed #f16624;
    border-radius: 5px;
    background: white;
    margin: 10px 0;
}
.dropzone.hovering {
    border: 2px solid #f16624;
    color: #dadada !important;
}
.dropzone .file-label {
    font-size: 1.2em;
}
progress::-webkit-progress-value {
    transition: width 0.1s ease;
}

 

First of all after rendering out the specific styles of the application.We will make the directive for making the drag and drop functionality in angular application.

ng g directive dropzone

 

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

@Directive({
  selector: '[dropzone]'
})
export class DropzoneDirective {

  @Output() dropped =  new EventEmitter<FileList>();
  @Output() hovered =  new EventEmitter<boolean>();

  @HostListener('drop', ['$event'])
  onDrop($event) {
    $event.preventDefault();
    this.dropped.emit($event.dataTransfer.files);
    this.hovered.emit(false);
  }

  @HostListener('dragover', ['$event'])
  onDragOver($event) {
    $event.preventDefault();
    this.hovered.emit(true);
  }

  @HostListener('dragleave', ['$event'])
  onDragLeave($event) {
    $event.preventDefault();
    this.hovered.emit(false);
  }
}

 

Step 2 – Uploader Component

 

ng g component uploader

 

<div class="dropzone" 
     dropzone
     (hovered)="toggleHover($event)"
     (dropped)="onDrop($event)"
     [class.hovering]="isHovering">


     <h3>AngularFire Drop Zone</h3>
     <p>Drag and Drop a File</p>
</div>

<h3>Uploads</h3>

<div *ngFor="let file of files">
  <upload-task [file]="file"></upload-task>
</div>

 

import { Component } from '@angular/core';

@Component({
  selector: 'uploader',
  templateUrl: './uploader.component.html',
  styleUrls: ['./uploader.component.scss']
})
export class UploaderComponent {

  isHovering: boolean;

  files: File[] = [];

  toggleHover(event: boolean) {
    this.isHovering = event;
  }

  onDrop(files: FileList) {
    for (let i = 0; i < files.length; i++) {
      this.files.push(files.item(i));
    }
  }
}

 

Step 3 – Upload Task Component

 

ng g component upload-task

 

<div *ngIf="percentage | async as pct">
  <progress [value]="pct" max="100"></progress>
  {{ pct | number }}%
</div>



<div *ngIf="snapshot | async as snap">

  {{ snap.bytesTransferred }} of {{ snap.totalBytes }} 

  <div *ngIf="downloadURL as url">
    <h3>Results!</h3>
    <img [src]="url"><br>
    <a [href]="url" target="_blank" rel="noopener">Download Me!</a>
  </div> 

  <button (click)="task.pause()" [disabled]="!isActive(snap)">Pause</button>
  <button (click)="task.cancel()" [disabled]="!isActive(snap)">Cancel</button>
  <button (click)="task.resume()" [disabled]="!(snap?.state === 'paused')">Resume</button>
</div>

 

import { Component, OnInit, Input, ChangeDetectorRef } from '@angular/core';
import { AngularFireStorage, AngularFireUploadTask } from '@angular/fire/storage';
import { AngularFirestore } from '@angular/fire/firestore';
import { Observable } from 'rxjs';
import { finalize, tap } from 'rxjs/operators';

@Component({
  selector: 'upload-task',
  templateUrl: './upload-task.component.html',
  styleUrls: ['./upload-task.component.scss']
})
export class UploadTaskComponent implements OnInit {

  @Input() file: File;

  task: AngularFireUploadTask;

  percentage: Observable<number>;
  snapshot: Observable<any>;
  downloadURL: string;

  constructor(private storage: AngularFireStorage, private db: AngularFirestore) { }

  ngOnInit() {
    this.startUpload();
  }

  startUpload() {

    // The storage path
    const path = `test/${Date.now()}_${this.file.name}`;

    // Reference to storage bucket
    const ref = this.storage.ref(path);

    // The main task
    this.task = this.storage.upload(path, this.file);

    // Progress monitoring
    this.percentage = this.task.percentageChanges();

    this.snapshot   = this.task.snapshotChanges().pipe(
      tap(console.log),
      // The file's download URL
      finalize( async() =>  {
        this.downloadURL = await ref.getDownloadURL().toPromise();

        this.db.collection('files').add( { downloadURL: this.downloadURL, path });
      }),
    );
  }

  isActive(snapshot) {
    return snapshot.state === 'running' && snapshot.bytesTransferred < snapshot.totalBytes;
  }

}

Leave a Reply