Angular 6 Firebase – Upload/Display/Delete Files from Storage

In the post, we have known how to upload file to Firebase Storage. This tutorial shows you way to upload, get, delete Files in a simple Angular 6 App.

I. Technology

– Angular 6
– AngularFire2 5.0

II. How to do

1. Set up the Firebase Project & Install AngularFire2

Please visit this post to know step by step.

2. Upload File Service

– upload file to Storage and file’s info to Database.
– get List Files from Firebase Storage by files’info (name/url) stored in Database.
– delete file with 2 steps: delete file’s info from Database, then delete file from Storage

export class UploadFileService {

  private basePath = '/uploads';

  constructor(private db: AngularFireDatabase) { }

  pushFileToStorage(fileUpload: FileUpload) {
    const storageRef = firebase.storage().ref();
    storageRef.child(`${this.basePath}/${fileUpload.file.name}`).put(fileUpload.file);

    fileUpload.url = downloadURL;
    fileUpload.name = fileName;
    this.saveFileData(fileUpload);
  }

  private saveFileData(fileUpload: FileUpload) {
    this.db.list(`${this.basePath}/`).push(fileUpload);
  }

  getFileUploads(numberItems): AngularFireList {
    return this.db.list(this.basePath, ref =>
      ref.limitToLast(numberItems));
  }

  deleteFileUpload(fileUpload: FileUpload) {
    this.deleteFileDatabase(fileUpload.key)
      .then(() => {
        this.deleteFileStorage(fileUpload.name);
      })
      .catch(error => console.log(error));
  }

  private deleteFileDatabase(key: string) {
    return this.db.list(`${this.basePath}/`).remove(key);
  }

  private deleteFileStorage(name: string) {
    const storageRef = firebase.storage().ref();
    storageRef.child(`${this.basePath}/${name}`).delete();
  }
}

To know how to save file info to Firebase Realtime Database, please visit previous post:
Angular 4 Firebase – Upload File to Storage

3. Get and display List of Files
import { map } from 'rxjs/operators';

import { UploadFileService } from '../upload-file.service';

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

  fileUploads: any[];

  constructor(private uploadService: UploadFileService) { }

  ngOnInit() {
    // Use snapshotChanges().pipe(map()) to store the key
    this.uploadService.getFileUploads(6).snapshotChanges().pipe(
      map(changes =>
        changes.map(c => ({ key: c.payload.key, ...c.payload.val() }))
      )
    ).subscribe(fileUploads => {
      this.fileUploads = fileUploads;
    });
  }
}

HTML template:

{{file.name}}

III. Practice

1. Project Overview
1.1 Goal

We will build an Angular 6 Firebase App that can:
– helps user choose file from local and upload it to Firebase Storage
– show progress with percentage
– save file metadata to Firebase Realtime Database
(Functions above from the posts: Angular 4 Firebase – Upload File to Storage)
– get list Files and display

angular-6-firebase-storage-tutorial-upload-get-files-storage-result

1.2 Structure

angular-6-firebase-storage-tutorial-upload-get-files-storage-project-structure

2. Step by step
2.1 Set up the Firebase Project & Install AngularFire2

Please visit this post to know step by step.

*Note: Don’t forget to set RULES for public read/write Database and Storage.

angular-6-firebase-storage-tutorial-upload-get-files-storage-rules

2.2 Add Firebase config to environments variable

Open /src/environments/environment.ts, add your Firebase configuration that we have saved when Popup window was shown:

export const environment = {
  production: false,
  firebase: {
    apiKey: 'xxx',
    authDomain: 'jsa-angular6.firebaseapp.com',
    databaseURL: 'https://jsa-angular6.firebaseio.com',
    projectId: 'jsa-angular6',
    storageBucket: 'jsa-angular6.appspot.com',
    messagingSenderId: 'xxx'
  }
};
2.3 Create Service & Components

Run the commands below:
ng g s upload/UploadFile
ng g c upload/FormUpload
ng g c upload/ListUpload
ng g c upload/DetailsUpload

2.4 Setup @NgModule

app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AngularFireDatabaseModule } from 'angularfire2/database';
import { AngularFireModule } from 'angularfire2';
import { environment } from '../environments/environment';

import { AppComponent } from './app.component';
import { FormUploadComponent } from './upload/form-upload/form-upload.component';
import { ListUploadComponent } from './upload/list-upload/list-upload.component';
import { DetailsUploadComponent } from './upload/details-upload/details-upload.component';

@NgModule({
  declarations: [
    AppComponent,
    FormUploadComponent,
    ListUploadComponent,
    DetailsUploadComponent
  ],
  imports: [
    BrowserModule,
    AngularFireModule.initializeApp(environment.firebase),
    AngularFireDatabaseModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }
2.5 Model Class

fileupload.ts

export class FileUpload {

    key: string;
    name: string;
    url: string;
    file: File;

    constructor(file: File) {
        this.file = file;
    }
}
2.6 Service

upload-file.service.ts

import { Injectable } from '@angular/core';
import { AngularFireDatabase, AngularFireList } from 'angularfire2/database';
import * as firebase from 'firebase/app';
import 'firebase/storage';

import { FileUpload } from './fileupload';

@Injectable({
  providedIn: 'root'
})
export class UploadFileService {

  private basePath = '/uploads';

  constructor(private db: AngularFireDatabase) { }

  pushFileToStorage(fileUpload: FileUpload, progress: { percentage: number }) {
    const storageRef = firebase.storage().ref();
    const uploadTask = storageRef.child(`${this.basePath}/${fileUpload.file.name}`).put(fileUpload.file);

    uploadTask.on(firebase.storage.TaskEvent.STATE_CHANGED,
      (snapshot) => {
        // in progress
        const snap = snapshot as firebase.storage.UploadTaskSnapshot;
        progress.percentage = Math.round((snap.bytesTransferred / snap.totalBytes) * 100);
      },
      (error) => {
        // fail
        console.log(error);
      },
      () => {
        // success
        uploadTask.snapshot.ref.getDownloadURL().then(downloadURL => {
          console.log('File available at', downloadURL);
          fileUpload.url = downloadURL;
          fileUpload.name = fileUpload.file.name;
          this.saveFileData(fileUpload);
        });
      }
    );
  }

  private saveFileData(fileUpload: FileUpload) {
    this.db.list(`${this.basePath}/`).push(fileUpload);
  }

  getFileUploads(numberItems): AngularFireList {
    return this.db.list(this.basePath, ref =>
      ref.limitToLast(numberItems));
  }

  deleteFileUpload(fileUpload: FileUpload) {
    this.deleteFileDatabase(fileUpload.key)
      .then(() => {
        this.deleteFileStorage(fileUpload.name);
      })
      .catch(error => console.log(error));
  }

  private deleteFileDatabase(key: string) {
    return this.db.list(`${this.basePath}/`).remove(key);
  }

  private deleteFileStorage(name: string) {
    const storageRef = firebase.storage().ref();
    storageRef.child(`${this.basePath}/${name}`).delete();
  }
}
2.7 Form Upload Compoment

form-upload.component.ts

import { Component, OnInit } from '@angular/core';
import { UploadFileService } from '../upload-file.service';
import { FileUpload } from '../fileupload';

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

  selectedFiles: FileList;
  currentFileUpload: FileUpload;
  progress: { percentage: number } = { percentage: 0 };

  constructor(private uploadService: UploadFileService) { }

  ngOnInit() {
  }

  selectFile(event) {
    this.selectedFiles = event.target.files;
  }

  upload() {
    const file = this.selectedFiles.item(0);
    this.selectedFiles = undefined;

    this.currentFileUpload = new FileUpload(file);
    this.uploadService.pushFileToStorage(this.currentFileUpload, this.progress);
  }
}

form-upload.component.html:

{{progress.percentage}}%
2.8 DetailsUpload Component

details-upload.component.ts

import { Component, OnInit, Input } from '@angular/core';
import { FileUpload } from '../fileupload';
import { UploadFileService } from '../upload-file.service';

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

  @Input() fileUpload: FileUpload;

  constructor(private uploadService: UploadFileService) { }

  ngOnInit() {
  }

  deleteFileUpload(fileUpload) {
    this.uploadService.deleteFileUpload(fileUpload);
  }
}

details-upload.component.html

{{fileUpload.name}}

2.9 ListUpload Component

list-upload.component.ts

import { Component, OnInit } from '@angular/core';
import { map } from 'rxjs/operators';

import { UploadFileService } from '../upload-file.service';

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

  fileUploads: any[];

  constructor(private uploadService: UploadFileService) { }

  ngOnInit() {
    // Use snapshotChanges().pipe(map()) to store the key
    this.uploadService.getFileUploads(6).snapshotChanges().pipe(
      map(changes =>
        changes.map(c => ({ key: c.payload.key, ...c.payload.val() }))
      )
    ).subscribe(fileUploads => {
      this.fileUploads = fileUploads;
    });
  }
}

list-upload.component.html

List of Files
2.10 App Component

app.component.ts

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

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'JavaSampleApproach';
  description = 'Angular-Firebase Demo';
}

app.component.html

{{title}}

{{description}}



2.11 Check Result

Run the App, go to http://localhost:4200/.

angular-6-firebase-storage-tutorial-upload-get-files-storage-result

Check Firebase Console:
– Database:

angular-6-firebase-storage-tutorial-upload-get-files-storage-database-result

– Storage:

angular-6-firebase-storage-tutorial-upload-get-files-storage-storage-result

IV. Source Code

Angular6FirebaseStorage-files

4 thoughts on “Angular 6 Firebase – Upload/Display/Delete Files from Storage”

  1. I have seen a ton of posts on the same topic .
    This is the best, well organised post , this Is perfect example of showing how to do something.
    I’m loving it.
    I’m hearty thankful to the author of this post.
    Than you so much.

    1. Hi Nasir Ahamad,

      I am so glad to see your comment. It makes motivation for me to create more things useful for the reader of ozenero. 🙂

      Regards,
      ozenero.

Leave a Reply

Your email address will not be published. Required fields are marked *