TypeError: Object(…) is not a function with Firebase storage

I’ve been experiencing this issue for days now. I’m trying to upload a photo to Firebase Storage using the following code in Ionic 3:

import * as firebase from 'firebase/app';
import 'firebase/storage';
/// *** blah blah blah
try{
firebase.storage().ref(url).putString(base64image, 'base64', {contentType: 'image/jpg'})
          .then((path)=>resolve(path.downloadURL))
          .catch((e)=>{reject(e)});
}catch (error) {
      console.warn("What the heck? ", error);
}

yet everytime I run it, I get the error

ERROR Error: Uncaught (in promise): TypeError: Object(...) is not a function TypeError: Object(...) is not a function at handler (vendor.js:152661)...

referring to the putString(…) function. Annoyingly, it doesn’t even get caught by the try/catch.

What’s wrong with this thing?? Please help! Thanks.

can you add the error handler to see if there is a better error message?

try {
  firebase
    .storage()
    .ref(url)
    .putString(base64image, "base64", { contentType: "image/jpg" })
    .then(
      path => resolve(path.downloadURL),
      e => console.log(e)  //<-- maybe we can get more information?
    )
    .catch(e => {
      reject(e);
    });
} catch (error) {
  console.warn("What the heck? ", error);
}

Thanks. I tried the above and it didn’t even show that error. I tweaked it a bit…


try {
          console.log("Begin");//<-- this showed 
          firebase.storage().ref(url).putString(img, 'base64', {contentType: 'image/jpg'})
          .then(
            path => {console.log("done"); // <-- This DIDN'T show
                   resolve(path.downloadURL)},
            e => console.log(e)  //<-- maybe we can get more information?
          )
          .catch((e)=>{reject(e)});
        } catch (error) {
          console.warn("What the heck?? ", error);
        }

but still got the ‘not a function’ error.

try changing

firebase.storage().ref().putString(img, 'base64', {contentType: 'image/jpg'})

to

firebase.storage().ref().child(url)putString(img, 'base64', {contentType: 'image/jpg'})

i usually set the path/url using the child() method

Thanks. Tried that, got the same error.
For reference, I recently updated all modules to their latest versions. Here’s my ionic info

Ionic:

   Ionic CLI          : 5.4.12 (/usr/local/lib/node_modules/ionic)
   Ionic Framework    : ionic-angular 3.9.9
   @ionic/app-scripts : 3.2.4

Cordova:

   Cordova CLI       : 9.0.0 (cordova-lib@9.0.1)
   Cordova Platforms : android 8.1.0, ios 5.1.1
   Cordova Plugins   : no whitelisted plugins (21 plugins total)

Utility:

   cordova-res                          : not installed
   native-run (update available: 0.3.0) : 0.2.3

System:

   Android SDK Tools : 26.1.1 (/usr/local/share/android-sdk)
   ios-deploy        : 1.9.2
   ios-sim           : 8.0.2
   NodeJS            : v10.15.0 (/usr/local/bin/node)
   npm               : 6.13.3
   OS                : macOS High Sierra
   Xcode             : Xcode 10.1 Build version 10B61

need to see more code, where is the string you are trying to put coming from

Actually it’s from a function.

// Add image to storage
  addImageToStorage(url, img):Promise<string>
  {
    return new Promise((resolve, reject)=>{
        try {
          console.log("Begin");
          firebase.storage().ref().child(url).putString(img, 'base64', {contentType: 'image/jpg'})
          .then(
            path => {console.log("done");resolve(path.downloadURL)},
            e => console.log(e)  //<-- maybe we can get more information?
          )
          .catch((e)=>{reject(e)});
        } catch (error) {
          console.warn("What the heck?? ", error);
        }
    })
  }

The img parameter is the image data retrieved from the photo gallery

var cameraoptions=
    {
      quality : 75,
        destinationType : env.camera.DestinationType.DATA_URL,
        sourceType : env.camera.PictureSourceType.PHOTOLIBRARY,
        allowEdit : true,
        encodingType: env.camera.EncodingType.JPEG,
        targetWidth: 300,
        targetHeight: 300
    };

this.camera.getPicture(cameraoptions)
      .then(imageData => {
        return (imageData); //<-- the image
      })

Where is the code where you are actually calling the upload function, there is no clarity here on how you are using the two together?

It’s all over the place, but here are the pieces…

/* request-form.ts */

import { FirebaseProvider } from '../../providers/firebase/firebase';
//***

base64Image: string="assets/img/no-picture.png";
photoUpdated:boolean=false;

constructor(public navCtrl: NavController, public navParams: NavParams, private toolbox:ToolboxProvider
    ,public actionSheetCtrl: ActionSheetController,private fbase:FirebaseProvider) {
  }
//*** other stuff
presentActionSheet() // called to choose photo from gallery or camera. This is where imageData is set
{
    let actionSheet = this.actionSheetCtrl.create({
      title: 'Choose a photo',
      buttons: [
        {
          text: 'Camera',
          role: 'camera',
          handler: () => {
            this.toolbox.showGallery(true)
            .then((imageData:string)=>{
              this.base64Image = "data:image/jpeg;base64," + imageData;
              this.photo = imageData;
              this.photoUpdated=true;
            })
            .catch((err) => {
              console.log("camera.getPicture(1) error: ", Object.getOwnPropertyNames(err));
             });
          }
        },{
          text: 'Gallery',
          handler: () => {
            this.toolbox.showGallery()
            .then((imageData:string)=>{
              this.base64Image = "data:image/jpeg;base64," + imageData;
              this.photo = imageData;
              this.photoUpdated=true;
            })
            .catch((err) => {
              console.log("camera.getPicture(2) error: ", JSON.stringify(err, Object.getOwnPropertyNames(err)));
             });
          }
        },{
          text: 'Cancel',
          role: 'cancel',
          handler: () => {
            console.log('Cancel clicked');
          }
        }
      ]
    });
    actionSheet.present();
  }// Present action sheet

SaveRequest()//<!-- where the upload happens
{ //*** validation and stuff goes here

    let env=this;
    var reqId=this.objRequest.id;
    this.fbase.addImageToStorage("/request_photos/" + reqId + "/photo.jpg",env.photo)
          .then((url)=>{console.log("uploaded to ", url)})
          .catch((e)=>{console.log("Help...", e)});
        console.log("Done");
    //*** etc etc
}
/* firebase.ts*/
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Platform} from 'ionic-angular';

import * as firebase from 'firebase/app';
import 'firebase/database';
import 'firebase/storage';

//** other stuff

  
  // Add image to storage
  addImageToStorage(url, img):Promise<string>
  {
    return new Promise((resolve, reject)=>{
        try {
          console.log("Begin");
          firebase.storage().ref().child(url).putString(img, 'base64', {contentType: 'image/jpg'})
          .then(
            path => {console.log("done");resolve(path.downloadURL)},
            e => console.log(e)  //<-- maybe we can get more information?
          )
          .catch((e)=>{reject(e)});
        } catch (error) {
          console.warn("What the heck?? ", error);
        }
    })
  }