frankied003
frankied003

Reputation: 516

Trouble with multiple firebase image upload with progress

I'm trying to upload multiple images to firebase at once. It is doing that, but the returned url array of those cloud image links are too late since the post is already being sent with an empty array. Here is my code:

// uploading media files using promises
  async uploadMedia(mediaFile: string){
      const extension = mediaFile.split('.')[mediaFile.split('.').length - 1];
      const mediaFileName = `${Math.round(Math.random()*100000000000)}.${extension}`;
      this.uploadProgress = 0;
      const response = await fetch(mediaFile);
      const blob = await response.blob();
      const storageRef = storage.ref(`${mediaFileName}`).put(blob);
      return storageRef.on(`state_changed`,snapshot=>{
        this.uploadProgress = (snapshot.bytesTransferred/snapshot.totalBytes);
      }, error=>{
        this.error = error.message;
        this.submitting = false;
        this.uploadingMedia = false;
        return;
      },
      async () => {
        // check whether the media is an image or a video and add to correct arrays
        if(extension == "png" || extension == "jpg"){
          return storageRef.snapshot.ref.getDownloadURL().then(async (url)=>{
            this.firebaseImageUrls = [...this.firebaseImageUrls, url];
            return;
          });
        }
        else{
          return storageRef.snapshot.ref.getDownloadURL().then(async (url)=>{
            this.firebaseVideoUrls = [...this.firebaseVideoUrls, url];
            return;
          });
        }
      });
  }

Where everything is being called:

await Promise.all(this.props.store.selectedImagesArray.map(async (file:string) => {
        await this.uploadMedia(file);
      }))
this.submitPost(); // this submits everything with the firebaseImageUrls

any help is appreciated

Upvotes: 0

Views: 169

Answers (2)

frankied003
frankied003

Reputation: 516

Figured it out. I had to make a promise and resolve the promise for each upload task and then loop through all the files doing this. Then when all the files are completely uploaded and the loop is completed, then I can submit the post with the files that are in firebaseImageUrls.

async uploadMedia(mediaFile: string){
    return new Promise(async (resolve, reject) => {
      //making the uploading task for one file
      const extension = mediaFile.split('.')[mediaFile.split('.').length - 1];
      const mediaFileName = `${Math.round(Math.random()*100000000000)}.${extension}`;
      const response = await fetch(mediaFile);
      const blob = await response.blob();
      const storageRef = storage.ref(`${mediaFileName}`);
      const task = storageRef.put(blob);

      task.on(`state_changed`,snapshot=>{
        this.uploadProgress = (snapshot.bytesTransferred/snapshot.totalBytes);
      }, error=>{
        this.error = error.message;
        this.submitting = false;
        this.uploadingMedia = false;
        return;
      },
      async () => {
        if(extension == "png" || extension == "jpg"){
          task.snapshot.ref.getDownloadURL().then((url:any)=>{
            console.log(url);
            resolve(url);
          });
        }
        else{
          task.snapshot.ref.getDownloadURL().then((url:any)=>{
            console.log(url);
            resolve(url);
          });
        }
      });
    })
  }

The loop:

for(var i = 0; i < this.props.store.selectedImagesArray.length; i++){
        const imageUrl = await this.uploadMedia(this.props.store.selectedImagesArray[i]);
        this.firebaseImageUrls = [...this.firebaseImageUrls, imageUrl];
}
this.submitPost();

Upvotes: 0

lex82
lex82

Reputation: 11317

The problem seems to be that storageRef.on() does not return a promise. It just registers the handlers. I'm not an expert on firebase. Maybe the put(blob) returns a promise that you can use.

Upvotes: 1

Related Questions