Ionic 5 Upload Image or File to Firebase Storage with Progress Bar

Ionic 5 Angular Image/File upload tutorial; This comprehensive guide will teach how to upload images & files to Firebase storage and display file and image uploading progress with progress percentage bar in Ionic Angular application with the help of npm Firebase and AngualrFire 2 packages.

Firebase is a profound backend as a service BaaS which offers valuable services which are accessible through Firebase configuration keys or API.

When it comes to application development, nothing is better than Firebase; it opens the doors of countless opportunities through its robust features. This guide explains how to use Firebase with Ionic and explains step-by-step how to use Firebase storage in Ionic 5 for image uploading, so let us begin this tutorial.

Ionic 5 Upload File/Image to Firebase Storage with Progress Bar

  • Step 1: Set Up Ionic Angular Project
  • Step 2: Add Firebase and AngularFire 2 in Ionic
  • Step 3: Setup Firebase Project & Firebase Storage
  • Step 4: Add Firebase Credentials in Environment
  • Step 5: Update Angular Fire Modules in App Module
  • Step 6: Create Angular File Size Filter
  • Step 7: Implement File/Image Uploading in Ionic
  • Step 8: Start Ionic Application

Set Up Ionic Angular Project

If you have not created the Ionic app yet, then follow the given instructions to create a new Ionic Angular app:

Install Ionic command-line-interface tool:

npm install -g @ionic/cli

Next, install the new Ionic Angular app:

ionic start ionic-image-upload-app blank --type=angular

Head over to the app’s root:

cd ionic-image-upload-app

Add Firebase and AngularFire 2 in Ionic

Type the command in the command prompt and install angular fire 2 and firebase packages simultaneously from the npm library.

npm i firebase @angular/fire

Setup Firebase Project & Firebase Storage

Visit firebase.google.com website. Then, create a new firebase project:

Firebase Create Account

Next, add firebase project name:

Create a project

Next, add Firebase to your app:

add Firebase to app

Next, provide a project name to include Firebase to your web app:

add firebase

Now, copy Firebase configuration keys:

Firebase configuration keys

Once, you acquired the Firebase credentials, then ensure to enable the Firestore from the firebase dashboard.

Only for the demo purpose choose the “test mode”.

Now, set up Firebase storage permission, click on ‘Storage’, then head over to Rules and update the current rules with the given below rules.

Make sure to publish the new security rules.

Firebase storage allows store and get user-generated files like images, audio, and video without server-side code.

rules_version = '2';
service firebase.storage {
  match /b/{bucket}/o {
    match /{allPaths=**} {
      allow read, write: if request.auth == null;
    }
  }
}

Add Firebase Credentials in Environment File

Next, you need to add the firebase configuration keys in environment file.

Update environment.ts file:

export const environment = {
    production: false,
    firebaseConfig: {
        apiKey: "API_KEY",
        authDomain: "PROJECT_ID.firebaseapp.com",
        databaseURL: "https://PROJECT_ID.firebaseio.com",
        projectId: "PROJECT_ID",
        storageBucket: "PROJECT_ID.appspot.com",
        messagingSenderId: "SENDER_ID",
        appId: "APP_ID",
        measurementId: "G-MEASUREMENT_ID",
    }
};

Update Angular Fire Modules in App Module

Next, you need to import AngularFireModule, AngularFireStorageModule, AngularFirestoreModule and environment services in the main app module class to evoke the connection between ionic and firebase database.

Update app.module.ts file:

import { AngularFireModule } from '@angular/fire';
import { AngularFireStorageModule } from '@angular/fire/storage';
import { AngularFirestoreModule } from '@angular/fire/firestore';
import { environment } from '../environments/environment';

@NgModule({
  declarations: [...],
  entryComponents: [...],
  imports: [
    AngularFireModule.initializeApp(environment.firebaseConfig),
    AngularFireStorageModule,
    AngularFirestoreModule
  ],
  providers: [...],
  bootstrap: [...],
})

export class AppModule {}

Create Angular File Size Filter

Custom pipes are handy when it comes to aligning business logic throughout the angular app. You may manually create a custom pipe or take the help of the cli command.

Let us understand how to create a file size pipe filter to calculate the file size, so make sure to generate the pipe with the following angular cli command.

ng generate pipe fileSize

Next, open and update the newly created file-size.pipe.ts file:

import { Pipe, PipeTransform } from '@angular/core';

let SIZE_UNITS = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
let SIZE_UNITS_LARGE = ['Bytes', 'Kilobytes', 'Megabytes', 'Gigabytes', 'Pettabytes', 'Exabytes', 'Zettabytes', 'Yottabytes'];

@Pipe({
  name: 'fileSize'
})
export class FileSizePipe implements PipeTransform {

  transform(sizeBytes: number, sizeForm: boolean): string {

    let sizeUnits = sizeForm ? SIZE_UNITS_LARGE : SIZE_UNITS;
    
    let sizeRoundVal = Math.round(Math.log(sizeBytes)/Math.log(1024));
  	sizeRoundVal = Math.min(sizeRoundVal, sizeUnits.length - 1);
  	let size = sizeBytes / Math.pow(1024, sizeRoundVal);
  	let sizeFormat = Math.round(size * 100) / 100;
  	let sizeUnit = sizeUnits[sizeRoundVal];

  	return `${sizeFormat} ${sizeUnit}`;
  }

}

Now, head over to the home page module file and import and inject the custom pipe filter (FileSizePipe) in declarations array.

Add code in home.module.ts file:

import { FileSizePipe } from '../file-size.pipe';


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

export class HomePageModule {}

Implement Image Upload and Progress Bar in Ionic

You have to go to the home page HTML file and use the card component to create the file uploading component layout.

We have to create an image uploading component, file upload control, cancel, pause, and resume buttons, show a progress bar for tracking upload progress, and show the list of the uploaded files stored in the firebase storage.

Open and update home.page.html file:

<ion-header [translucent]="true">
  <ion-toolbar>
    <ion-title>Ionic 5 Firebase Image/File Upload Progress Bar</ion-title>
  </ion-toolbar>
</ion-header>

<ion-content>
  <ion-card *ngIf="!isImgUploading && !isImgUploaded">
    <ion-card-header>
      <ion-card-title>Select File</ion-card-title>
    </ion-card-header>

    <ion-button color="danger">
      <input type="file" class="upload" (change)="fileUpload($event.target.files)" />
    </ion-button>
  </ion-card>

  <ion-card *ngIf="isImgUploading && !isImgUploaded">
    <ion-card-header>
      <ion-card-title>Files selected: <b>{{ FileName }}</b></ion-card-title>
    </ion-card-header>

    <ion-card-content>
      <div *ngIf="progressNum | async as percentage">
        Progress: {{ percentage | number }}%
        <ion-progress-bar value="{{ percentage / 100 }}"></ion-progress-bar>
      </div>
      <div *ngIf="progressSnapshot | async as pSnapshot">
        Image size: {{ pSnapshot.totalBytes | fileSize }} Transfered:
        {{ pSnapshot.bytesTransferred | fileSize }}
        <div *ngIf="progressSnapshot && pSnapshot.bytesTransferred != pSnapshot.totalBytes">
          <ion-button color="danger" fill="outline" size="small" (click)="ngFireUploadTask.cancel()">Cancel</ion-button>
          <ion-button color="secondary" fill="outline" size="small" (click)="ngFireUploadTask.pause()">Pause
          </ion-button>
          <ion-button color="dark" fill="outline" size="small" (click)="ngFireUploadTask.resume()" class="button">Resume
          </ion-button>
        </div>
      </div>
    </ion-card-content>
  </ion-card>

  <ion-card *ngIf="!isImgUploading && isImgUploaded">
    <ion-card-header>
      <ion-card-title>
        <b>{{ FileName }}</b> Uploaded
      </ion-card-title>
    </ion-card-header>

    <ion-card-content>
      <div *ngIf="fileUploadedPath | async as fileUrl">
        <img [src]="fileUrl" />
        <a [href]="fileUrl" rel="nofollow" target="_blank">Download</a>
      </div>
      File Size: {{ FileSize | fileSize }}
    </ion-card-content>
  </ion-card>

  <ion-card>
    <ion-card-header>
      <ion-card-title>
        Uploaded Files Collection
      </ion-card-title>
    </ion-card-header>
    <ion-card *ngFor="let img of files | async">
      <ion-card-header>
        <ion-card-title>
          {{ img.name }}
        </ion-card-title>
      </ion-card-header>

      <ion-card-content>
        <img [src]="img.filepath" />
        <a [href]="img.filepath" rel="nofollow" target="_blank">Download</a>
      </ion-card-content>
    </ion-card>
  </ion-card>
</ion-content>

The following code comprises uploading the files, showing image upload progress witch cancel, pause, and resume buttons, display uploaded image with the image download button, fetch all the stored images in Firebase storage.

Open and update home.page.ts file:

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

export interface FILE {
  name: string;
  filepath: string;
  size: number;
}

@Component({
  selector: 'app-home',
  templateUrl: 'home.page.html',
  styleUrls: ['home.page.scss'],
})

export class HomePage {

  ngFireUploadTask: AngularFireUploadTask;

  progressNum: Observable<number>;

  progressSnapshot: Observable<any>;

  fileUploadedPath: Observable<string>;

  files: Observable<FILE[]>;

  FileName: string;
  FileSize: number;

  isImgUploading: boolean;
  isImgUploaded: boolean;

  private ngFirestoreCollection: AngularFirestoreCollection<FILE>;
  
  constructor(
    private angularFirestore: AngularFirestore,
    private angularFireStorage: AngularFireStorage
  ) {
    this.isImgUploading = false;
    this.isImgUploaded = false;
    
    this.ngFirestoreCollection = angularFirestore.collection<FILE>('filesCollection');
    this.files = this.ngFirestoreCollection.valueChanges();
  }


  fileUpload(event: FileList) {
      
      const file = event.item(0)

      if (file.type.split('/')[0] !== 'image') { 
        console.log('File type is not supported!')
        return;
      }

      this.isImgUploading = true;
      this.isImgUploaded = false;

      this.FileName = file.name;

      const fileStoragePath = `filesStorage/${new Date().getTime()}_${file.name}`;

      const imageRef = this.angularFireStorage.ref(fileStoragePath);

      this.ngFireUploadTask = this.angularFireStorage.upload(fileStoragePath, file);

      this.progressNum = this.ngFireUploadTask.percentageChanges();
      this.progressSnapshot = this.ngFireUploadTask.snapshotChanges().pipe(
        
        finalize(() => {
          this.fileUploadedPath = imageRef.getDownloadURL();
          
          this.fileUploadedPath.subscribe(resp=>{
            this.fileStorage({
              name: file.name,
              filepath: resp,
              size: this.FileSize
            });
            this.isImgUploading = false;
            this.isImgUploaded = true;
          },error => {
            console.log(error);
          })
        }),
        tap(snap => {
            this.FileSize = snap.totalBytes;
        })
      )
  }


  fileStorage(image: FILE) {
      const ImgId = this.angularFirestore.createId();
      
      this.ngFirestoreCollection.doc(ImgId).set(image).then(data => {
        console.log(data);
      }).catch(error => {
        console.log(error);
      });
  }  

}

Start Ionic Application

There are two ways to test the image uploading in Ionic:

One way is to install the ionic lab package with dev dependency:

npm i @ionic/lab --save-dev

Start the ionic development server and run an app on the emulator:

ionic serve -l

Or, If you want to run app on the native device then you have to:

Add the platform:

# iOS
ionic cordova platform add ios

# Android
ionic cordova platform add android

Next, create the runnable build:

# iOS
ionic cordova build ios

# Android
ionic cordova build android

Finally, start the app on the device:

# iOS
ionic cordova run ios -l

# Android
ionic cordova run android -l

Ionic Image Upload progress bar tutorial

Conclusion

Ionic 5 upload file to firebase storage tutorials is ended. In this extensive guide, we comprehended how to use upload files and images to Firebase storage through the Ionic, angular app. Not just that, we also understood how to show the percentage progress bar to show the file uploading progress visually. If you loved this example, make sure to share this guide with others.

We hope it will surely help you; download the entire project code from GitHub.