1

I have already successfully uploaded images into my firebase storage, but I also want to retrieve the download URL and add it to my firestore database. Console logging "URL" returns me the link I want. But I am having trouble using it.

I have tried this.profileImage = URL but the console will always return me error Cannot set property 'profileImage' of undefined. I have it defined by writingprofileImage above the constructor.

I have also tried placing the entire firestore function inside but the console will return cannot read property 'firestore' of undefined. I am using Ionic 5.

imageRef.getDownloadURL().then((url)=> {
    this.firestore.collection('users').doc(this.user.id).update({image.url})
       console.log("this is my image" + url)
})

this is what I currently have

uploadImage(imageURI) {
    return new Promise<any>((resolve, reject) => {
      let storageRef = firebase.storage().ref();
      const imageRef = storageRef.child('image').child(this.createFileName());
      this.encodeImageUri(imageURI, function (image64) {
        imageRef.putString(image64, 'data_url')
          .then(function (snapshot) {
            console.log(snapshot)
            resolve(snapshot.downloadURL)
            imageRef.getDownloadURL().then((url)=> {
              this.profileImage = url
              console.log(this.profileImage)
              console.log("this is my image" + url)
            })
          }, err => {
            reject(err);
          })
      })
    })
  }
encodeImageUri(imageUri, callback) {
    var c = document.createElement('canvas');
    var ctx = c.getContext("2d");
    var img = new Image();
    img.onload = function () {
      var aux: any = this;
      c.width = aux.width;
      c.height = aux.height;
      ctx.drawImage(img, 0, 0);
      var dataURL = c.toDataURL("image/jpeg");
      callback(dataURL);
    };
    img.src = imageUri;
  };
  • The line contains this :`this.profileImage = url` is suspicious. You have atleast 2 nested scopes on that line. Are you sure your are assigning to the correct this? If you are aiming to assign the component property you need to change the functions into arrow functions – Eldar Jul 26 '20 at 05:59

1 Answers1

1

If you are using a "normal" function instead of an arrow function you lose the "this context".

Difference between an arrow function and a "normal" function: https://stackoverflow.com/a/34361380/11592273

uploadImage(imageURI) {
    return new Promise<any>((resolve, reject) => {
      let storageRef = firebase.storage().ref();
      const imageRef = storageRef.child('image').child(this.createFileName());
        // replaced with an arrow function
      this.encodeImageUri(imageURI, (image64) => {
        imageRef.putString(image64, 'data_url')
             // replaced with an arrow function
          .then((snapshot) => {
            console.log(snapshot)
            imageRef.getDownloadURL().then((url)=> {
              this.profileImage = url
              console.log(this.profileImage)
              console.log("this is my image" + url)
                // call the resolve method after all async tasks are complteded.
              resolve(snapshot.downloadURL)
            })
          }, err => {
            reject(err);
          })
      })
    })
  }

Also, I would recommend using await/async instead of then/catch.

async uploadImage(imageURI) {
  const storageRef = firebase.storage().ref();
  const imageRef = storageRef.child('image').child(this.createFileName());
  const image64 = await this.encodeImageUri(imageURI);
  const snapshot = await imageRef.putString(image64, 'data_url');
  const url = imageRef.getDownloadURL();
  this.profileImage = url;
  return snapshot.downloadURL;
}
M. Münker
  • 36
  • 3