Search code examples
firebasefirebase-storageangularfire2

Firebase Storage download url not available after upload


I am using Angular and AngularFire2. I am trying to upload an image to firebase storage, then once that is done I am take that reference and get the download url and upload it to the database. For some reason even though the upload is complete and I have the snapshot, when I try to use that in order to get the URL it's giving me an error that the object does not exist. Any thoughts on what I might be doing wrong?

task.snapshotChanges().pipe(
        concatMap(snap => {
          return snap.ref.getDownloadURL()
        }),
        concatMap(url => this.db.collection('library').add({
          name: this.image.name,
          path: path,
          largeUrl: url
        }))
      ).subscribe(ref => {
        this.completed = true;
      }, error => console.log(error));

error:

Firebase Storage: Object 'library/1542515976022_lemonade-smoothie.jpg' does not exist.

Solution

  • Ok, so my issue was not really understanding concatMap. I thought it wasn't called until the last onNext() of the upload Observable. It was being called on the first onNext(), which means the file had not completely updated. Below is what I ended up doing, although it seems like there should be another way. What I would like is to only switch to the new Observable track if the downloaded bytes equals the total bytes. I'm not sure how to do this with RxJS though. If anyone had any thoughts let me know.

    task
       .snapshotChanges()
       .pipe(finalize(() => this.uploadToDb(path)))
       .subscribe();
    
    uploadToDb(path: string) {
        this.storage
          .ref(path)
          .getDownloadURL()
          .pipe(
            concatMap(url =>
              this.db.collection('library').add({
                name: this.image.name,
                path: path,
                largeUrl: url
              })
            )
          )
          .subscribe(
            ref => (this.completed = true),
            error => {
              console.log(error);
              this.error = true;
            }
          );
      }