Asking for a recommedation: Local storage or Firebase Storage?

Hi, I have to take a decition about how to manage the storing image process…

I think it’s better to storage the images locally, show it to the user, and, when the user confirms is correct, start the Firebase Storage saving process. The point is that I don’t find a example about how to show the images from the local storage (File:///…/cache/whatever.jpg)…

Alternatively I could store, from the beggining, in Firebase Storage the images and when the user confirm is correct I could rename it with the definitive name. I know how to do this way, but I don’t like this solution much as if the user interrupt the process I would have “lost” images overloading the database.

What do you recommend me? Do you have an example about how to show images from cache local storage?

Thanks in advance!

Better to put image files in Firebase Storage, which is different from both Firestore and Firebase.

Yes, sorry, this is what I wanted to say… post updated!

I would store images locally until approved by the user.

How are you attempting to show local images?

1 Like

Thanks for the response!

I’m trying to do it this way:

    const imageUri = await this.camera.getPicture(options)
      .then(imageUri => {
        console.log("imageUri: " + imageUri);
        this.photo = imageUri;

This is what I get:

“file:///storage/emulated/0/Android/data/omnibay.unlimited.tititools.com/cache/.Pic.jpg?1516695906122”

I try to show it with (doesn’t work):

  <ion-card>
    <img src="{{this.photo}}" alt="Avatar" />
  </ion-card>

I continued trying, but still not working…

I paste the code (copied from https://devdactic.com/ionic-2-images/)

The path I get is the following: file:///data/user/0/io.ionic.starter/files/1518030884511.jpg

It’s still not being recognidzed from the view (it appears the small image icon)

<ion-header>
  <ion-navbar color="primary">
    <ion-title>
      Devdactic Image Upload
    </ion-title>
  </ion-navbar>
</ion-header>
 
<ion-content padding>
  <img src="{{pathForImage(lastImage)}}" style="width: 100%" [hidden]="lastImage === null">
  <h3 [hidden]="lastImage !== null">Please Select Image!</h3>
</ion-content>
 
<ion-footer>
  <ion-toolbar color="primary">
    <ion-buttons>
      <button ion-button icon-left (click)="presentActionSheet()">
        <ion-icon name="camera"></ion-icon>Select Image
      </button>
      <button ion-button icon-left (click)="uploadImage()" [disabled]="lastImage === null">
        <ion-icon name="cloud-upload"></ion-icon>Upload
      </button>
    </ion-buttons>
  </ion-toolbar>
</ion-footer>
import { Component } from '@angular/core';
import { NavController, ActionSheetController, ToastController, Platform, LoadingController, Loading } from 'ionic-angular';

import { File } from '@ionic-native/file';
import { Transfer, TransferObject } from '@ionic-native/transfer';
import { FilePath } from '@ionic-native/file-path';
import { Camera } from '@ionic-native/camera';

import { StatusBar } from '@ionic-native/status-bar';


declare var cordova: any;

@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {
  lastImage: string = null;
  loading: Loading;

  constructor(private statusBar: StatusBar, public navCtrl: NavController, private camera: Camera, private transfer: Transfer, private file: File, private filePath: FilePath, public actionSheetCtrl: ActionSheetController, public toastCtrl: ToastController, public platform: Platform, public loadingCtrl: LoadingController) {
    // let status bar overlay webview
    this.statusBar.overlaysWebView(true);

    // set status bar to white
    this.statusBar.backgroundColorByHexString('#ffffff');

  }

  public presentActionSheet() {
    let actionSheet = this.actionSheetCtrl.create({
      title: 'Select Image Source',
      buttons: [
        {
          text: 'Load from Library',
          handler: () => {
            this.takePicture(this.camera.PictureSourceType.PHOTOLIBRARY);
          }
        },
        {
          text: 'Use Camera',
          handler: () => {
            this.takePicture(this.camera.PictureSourceType.CAMERA);
          }
        },
        {
          text: 'Cancel',
          role: 'cancel'
        }
      ]
    });
    actionSheet.present();
  }

  public takePicture(sourceType) {
    // Create options for the Camera Dialog
    var options = {
      quality: 100,
      sourceType: sourceType,
      saveToPhotoAlbum: false,
      correctOrientation: true
    };

    // Get the data of an image
    this.camera.getPicture(options).then((imagePath) => {
      // Special handling for Android library
      if (this.platform.is('android') && sourceType === this.camera.PictureSourceType.PHOTOLIBRARY) {
        this.filePath.resolveNativePath(imagePath)
          .then(filePath => {
            let correctPath = filePath.substr(0, filePath.lastIndexOf('/') + 1);
            let currentName = imagePath.substring(imagePath.lastIndexOf('/') + 1, imagePath.lastIndexOf('?'));
            this.copyFileToLocalDir(correctPath, currentName, this.createFileName());
          });
      } else {
        var currentName = imagePath.substr(imagePath.lastIndexOf('/') + 1);
        var correctPath = imagePath.substr(0, imagePath.lastIndexOf('/') + 1);
        this.copyFileToLocalDir(correctPath, currentName, this.createFileName());
      }
    }, (err) => {
      this.presentToast('Error while selecting image: ' + err);
    });
  }

  // Create a new name for the image
  private createFileName() {
    var d = new Date(),
      n = d.getTime(),
      newFileName = n + ".jpg";
    return newFileName;
  }

  // Copy the image to a local folder
  private copyFileToLocalDir(namePath, currentName, newFileName) {
    let dataDirectory = cordova.file.dataDirectory;
    this.file.copyFile(namePath, currentName, dataDirectory, newFileName).then(success => {
      this.lastImage = newFileName;
    }, error => {
      this.presentToast('Error while storing file.');
    });
  }

  private presentToast(text) {
    let toast = this.toastCtrl.create({
      message: text,
      duration: 3000,
      position: 'top'
    });
    toast.present();
  }

  // Always get the accurate path to your apps folder
  public pathForImage(img) {
    if (img === null) {
      return '';
    } else {
      return cordova.file.dataDirectory + img;
    }
  }

  public uploadImage() {

    // File for Upload
    var targetPath = this.pathForImage(this.lastImage);

    // File name only
    var filename = this.lastImage;

    console.log(targetPath);
    console.log(filename)

  }

  public uploadImage2() {

    // Destination URL
    var url = "http://yoururl/upload.php";

    // File for Upload
    var targetPath = this.pathForImage(this.lastImage);

    // File name only
    var filename = this.lastImage;

    var options = {
      fileKey: "file",
      fileName: filename,
      chunkedMode: false,
      mimeType: "multipart/form-data",
      params: { 'fileName': filename }
    };

    const fileTransfer: TransferObject = this.transfer.create();

    this.loading = this.loadingCtrl.create({
      content: 'Uploading...',
    });
    this.loading.present();

    // Use the FileTransfer to upload the image
    fileTransfer.upload(targetPath, url, options).then(data => {
      this.loading.dismissAll()
      this.presentToast('Image succesful uploaded.');
    }, err => {
      this.loading.dismissAll()
      this.presentToast('Error while uploading file.');
    });
  }

}

Can you help with an example? I have found this info that I like, but I don’t know how to adapt it to ionic: https://www.html5rocks.com/es/tutorials/file/dndfiles/

That code is really old. Read the Javebratt blog, or Josh Morony’s blog.

OK, I will! Thanks!!

Hi! I’m not able to find more information. I’m trying to do with Media Capture plugin, and I get to access the camera captured image from this path: cdvfile://localhost/sdcard/Pictures/1518196433208.jpg

But not from file:///storage/emulated/0/Pictures/1518196433208.jpg

Maybe is something related with permissions?

It’s dificult to find a solution…

Firebase has 1GB free plan… you can use that.

Thanks, I am using firebase, but the point is that I want to store de image locally and show it to the user, and then use a button to upload it. :smiley: