Ionic 2 - Image Upload to Firebase ios - Creating an image format with an unknown type

When i use the below code i get the following error when running on iOS device. Everything is building fine. When i click the button to run the updateProfilePic () function my photo gallery is coming up and i can choose an image; however once i have chosen an image, the image is not uploaded to Firebase and i get the below logged error.

settings:

  • Ionic 2.0.0
  • Angular 2.2.1
  • Mac OS X El Capitan
  • Xcode 8.1
  • Cordova 6.5.0
  • ionic plugin add cordova-plugin-camera

Error: Creating an image format with an unknown type is an error

      var file: any;

      private updateProfilePic (): void {
      let cameraOptions = {
        sourceType: Camera.PictureSourceType.PHOTOLIBRARY,
        destinationType: Camera.DestinationType.FILE_URI,
        quality: 100,
        targetWidth: 1000,
        targetHeight: 1000,
        encodingType: Camera.EncodingType.JPEG,
        correctOrientation: true
      }

      Camera.getPicture(cameraOptions).then((imageData) => {
              this.file = imageData;
              var fileName = this.file.name;
              console.log(fileName);
              var storageRef = firebase.storage().ref('/userProfile/' + this.userProfile.currentUser.uid + '/' + fileName);
              console.log(storageRef);
              var uploadTask = storageRef.put(this.file);
              uploadTask.on('state_changed', function(snapshot){
              }, function(error){
              }, function(){
                var photoURL = uploadTask.snapshot.downloadURL;
                this.profileData.updateProfilePic(photoURL);
                });
          }, (error) => {
                alert(error);
                });
     }

you need a FileEntry object - https://github.com/apache/cordova-plugin-camera#take-a-picture-and-get-a-fileentry-object-

Thank you for for the reply. I tried to follow the instructions for FileEntry object, but i get the following typescript error on build:

property ‘resolveLocalFileSystemURL’ does not exist on type ‘Window’.

src/pages/profile/profile.ts

import { Camera } from ‘ionic-native’;
import { Transfer } from ‘ionic-native’;

getProfilePic () {
      let cameraOptions = {
        sourceType: Camera.PictureSourceType.PHOTOLIBRARY,
        destinationType: Camera.DestinationType.FILE_URI,
        quality: 100,
        targetWidth: 1000,
        targetHeight: 1000,
        encodingType: Camera.EncodingType.JPEG,
        correctOrientation: true
      }

      Camera.getPicture(cameraOptions).then((imageUri) => {
              console.log("Got the imageUri, now pass it to the getFileEntry function");
              this.getFileEntry(imageUri);
              }, (err) => {
                  // Handle error
                  });
      }

      getFileEntry(imageUri) {
        window.resolveLocalFileSystemURL(imageUri, function success(fileEntry) {
            console.log("got file: " + fileEntry.fullPath);
            this.updateProfilePic(fileEntry);

        }, function () {
          // If don't get the FileEntry (which may happen when testing
          // on some emulators), copy to a new FileEntry.
          // createNewFileEntry(imgUri);
          console.log("Error in getting FileEntry");
        });
      }

      updateProfilePic(fileEntry) {
          var fileName = fileEntry.name
          var storageRef = firebase.storage().ref('/userProfile/' + this.userProfile.currentUser.uid + '/' + fileName);
          var uploadTask = storageRef.put(fileEntry);
          uploadTask.on('state_changed', function(snapshot){
            }, function(error){
            }, function(){
                var photoURL = uploadTask.snapshot.downloadURL;
                this.profileData.updateProfilePic(photoURL);
                });
      }

did you load the file manager plugin?

I ran the ionic plugin add cordova-plugin-file-transfer command to load the file transfer plugin. Is there another plugin needed?

that is not the same… look at the documentation I provided… click the link to the correct plugin to install

https://www.npmjs.com/package/cordova-plugin-file

Oh, yes i already installed that plugin too… but still getting the same error property ‘resolveLocalFileSystemURL’ does not exist on type ‘Window’

:MyApp dev$ ionic plugin add cordova-plugin-file
Plugin "cordova-plugin-file" already installed on android.

Plugin "cordova-plugin-file" already installed on ios.

did you add

declare var window: any;

see this project https://github.com/aaronksaunders/firebaseStorage2/blob/master/src/pages/home/home.ts

look at:


and

hope that helps

Thanks, using declare var window: any; helped to remove the typescript error for property 'resolveLocalFileSystemURL' does not exist on type 'Window'.

However i still have build errors, but it looks like i’m missing something major. Looks like you are converting the FileEntry to a blob.

Where is any of this documented in Ionic or Firebase documents?

Now, that i have declared var window: any; here is the error i am getting on build.
TypeError: undefined is not an object (evaluating ‘Reflect.getMetadata’)

getProfilePic () {
  let cameraOptions = {
    sourceType: Camera.PictureSourceType.PHOTOLIBRARY,
    destinationType: Camera.DestinationType.FILE_URI,
    quality: 100,
    targetWidth: 1000,
    targetHeight: 1000,
    encodingType: Camera.EncodingType.JPEG,
    correctOrientation: true
  }

  Camera.getPicture(cameraOptions).then((imageUri) => {
          console.log("Got the imageUri, now pass it to the makeFileIntoBlob y function");
          this.makeFileIntoBlob(imageUri);
          }, (err) => {
              // Handle error
              });
  }

  makeFileIntoBlob(imageUri) {
  return new Promise((resolve, reject) => {
    window.resolveLocalFileSystemURL(imageUri, (fileEntry) => {

      fileEntry.file((resFile) => {

        var reader = new FileReader();
        reader.onloadend = (evt: any) => {
          var imgBlob: any = new Blob([evt.target.result], { type: 'image/jpeg' });
          imgBlob.name = 'sample.jpg';
          resolve(imgBlob);
          this.updateProfilePic(imgBlob);
        };

        reader.onerror = (e) => {
          console.log('Failed file read: ' + e.toString());
          reject(e);
        };

        reader.readAsArrayBuffer(resFile);
        });
      });
    });
  }

  updateProfilePic(imgBlob) {
      var fileName = imgBlob.name
      var storageRef = firebase.storage().ref('/userProfile/' + this.userProfile.currentUser.uid + '/' + fileName);
      var uploadTask = storageRef.put(imgBlob);
      uploadTask.on('state_changed', function(snapshot){
        }, function(error){
        }, function(){
            var photoURL = uploadTask.snapshot.downloadURL;
            this.profileData.updateProfilePic(photoURL);
            });
  }

there is not enough here for me to provide assistance since I cannot see a stack dump i have no idea where or what is causing the error… BTW why such large images for a phone?

    targetWidth: 1000,
    targetHeight: 1000,

the project I linked to works… compile it and take a look or provide more code/log information

Thank you for helping. I’m going to take a closer look at the link you sent and get back here later.

Thank you for the Help! i got it working after reviewing your code you linked. I hope Ionic and Firebase provide better integration documentation, that was not easy to understand without your help.

I still have some code clean up, but for others future reference below is the code to my profile.ts which uses a profile-data.ts Provider to read/write to Firebase.

import { Component } from '@angular/core';
import { NavController, NavParams, AlertController } from 'ionic-angular';
import { Platform, ActionSheetController } from 'ionic-angular';

import { Camera } from 'ionic-native';
import { Transfer } from 'ionic-native';

import { ProfileData } from '../../providers/profile-data';
import { AuthService } from '../../providers/auth-service';
import firebase from 'firebase';

import {TabsPage} from '../tabs/tabs';


declare var window: any;

/*
  Generated class for the Profile page.
  See http://ionicframework.com/docs/v2/components/#navigation for more info on
  Ionic pages and navigation.
*/
@Component({
  selector: 'page-profile',
  templateUrl: 'profile.html'
})
export class ProfilePage {
  tabsPage = TabsPage;
  public userProfile: any;
  testRadioOpen: boolean;
  public relationship: any;
  public file: any;
  public profilePic: any;
  public blob: any;
  public photoURL: any;



  constructor(public navCtrl: NavController, public navParams: NavParams, public profileData: ProfileData, public alertCtrl: AlertController, public actionSheetCtrl: ActionSheetController, public platform: Platform) {
  this.profileData = profileData;
  this.profileData.getUserProfile().on('value', (data) => {
      this.userProfile = data.val();
    });

  }

  ionViewDidLoad() {
    console.log('ionViewDidLoad ProfilePage');
  }

  getPicture() {

  // get picture from camera

  //console.log(Device)
  //let imageSource = (Device.isVirtual ? Camera.PictureSourceType.PHOTOLIBRARY : Camera.PictureSourceType.CAMERA);

  Camera.getPicture({
    sourceType: Camera.PictureSourceType.PHOTOLIBRARY,
    destinationType: Camera.DestinationType.FILE_URI,
    quality: 100,
    targetWidth: 500,
    targetHeight: 500,
    encodingType: Camera.EncodingType.JPEG,
    correctOrientation: true
  }).then((_imagePath) => {
    //alert('got image path ' + _imagePath);
    // convert picture to blob
    return this.makeFileIntoBlob(_imagePath);
  }).then((_imageBlob) => {
    //alert('got image blob ' + _imageBlob);

    // upload the blob
    return this.uploadToFirebase(_imageBlob);
  }).then((_uploadSnapshot: any) => {
    //alert('file uploaded successfully  ' + _uploadSnapshot.downloadURL);

    // store reference to storage in database
    return this.saveToUserProfile(_uploadSnapshot);

  }).then((_uploadSnapshot: any) => {
    //alert('file saved to asset catalog successfully  ');
  }, (_error) => {
    alert('Error ' + (_error.message || _error));
  });
}

makeFileIntoBlob(_imagePath) {

  // INSTALL PLUGIN - cordova plugin add cordova-plugin-file
  return new Promise((resolve, reject) => {
    window.resolveLocalFileSystemURL(_imagePath, (fileEntry) => {

      fileEntry.file((resFile) => {

        var reader = new FileReader();
        reader.onloadend = (evt: any) => {
          var imgBlob: any = new Blob([evt.target.result], { type: 'image/jpeg' });
          imgBlob.name = 'sample.jpg';
          resolve(imgBlob);
        };

        reader.onerror = (e) => {
          console.log('Failed file read: ' + e.toString());
          reject(e);
        };

        reader.readAsArrayBuffer(resFile);
      });
    });
  });
}

uploadToFirebase(_imageBlob) {
  var fileName = 'sample-' + new Date().getTime() + '.jpg';

  return new Promise((resolve, reject) => {
    var fileRef = firebase.storage().ref('/userProfile/' + this.profileData.currentUser.uid + '/' + fileName);

    var uploadTask = fileRef.put(_imageBlob);

    uploadTask.on('state_changed', (_snapshot) => {
      console.log('snapshot progess ' + _snapshot);
    }, (_error) => {
      reject(_error);
    }, () => {
      // completion...
      resolve(uploadTask.snapshot);
    });
  });
}

saveToUserProfile(_uploadSnapshot) {
  this.photoURL = _uploadSnapshot.downloadURL;
  this.profileData.updateProfilePic(this.photoURL);

}

profilePicActionSheet() {
    let profilePicSheet = this.actionSheetCtrl.create({
      title: 'Upload your Profile Picture',
      cssClass: 'action-sheets-basic-page',
      buttons: [
        {
          text: 'Take a Picture',
          role: 'destructive',
          icon: !this.platform.is('ios') ? 'camera' : null,
          handler: () => {
            console.log('Take a Picture clicked');
          }
        },{
          text: 'Select from Gallery',
          icon: !this.platform.is('ios') ? 'images' : null,
          handler: () => {
            console.log('Select from Gallery clicked');
            this.getPicture();
          }
        },{
          text: 'Cancel',
          role: 'cancel',
          icon: !this.platform.is('ios') ? 'close' : null,
          handler: () => {
            console.log('Cancel clicked');
          }
        }
      ]
    });
    profilePicSheet.present();
  }

}
1 Like

not sure why you would expect Firebase and Ionic to provide better documentation? Building solutions using three different frameworks will require some effort from the community to bring it all together.

My project has been available and is in the tutorials section of the forum, the documentation on using files from the camera is documented in the Camera plugin and uploading is included in the Firebase documentation

But I am glad you found a solution… please mark it has solved to help others who come along.

@aaronksaunders

Thanks for posting your Github project and Youtube video… Its been pretty helpful for me.

I’m having an issue though… and I’m wondering if you or someone else could help…
I’m trying to use your code for

makeFileIntoBlob(_imagePath)

I have stored a file Entry object from the camera… it looks like this:

Wen I pass the nativeURL of the file component into the makeFileIntoBlob function… It just hangs and never resolves…

Any clues?
(Running on android )

This is useless as Ionic View and Ionic DevApp are not compatible with file, file-path and file-transfer plug-ins.