I am having an issue with uploading multiple files asynchronously to Firebase storage and retrieving their URLs

My issue revolves around uploading multiple files to Firebase storage after adding an image. The upload works fine, but I encounter a problem when trying to retrieve the download URLs for these files. While getting URLs for multiple files is successful, I face issues with obtaining the URL for the separate image file. It seems to return null in this case. Just to provide some context, I am using Vue.js. Below are the methods I am utilizing, and all inputs seem to be correct.

methods:{
   async uploadImageFile() {
     var slugify = require('slugify')
     let imageName = this.$refs.image.files[0].name.split("".")[0]
     let ext = this.$refs.image.files[0]['name'].split("".")[1]
     this.blog.image = slugify(imageName)
     const {canvas} = this.$refs.cropper.getResult();
     if (canvas) {
       canvas.toBlob( blob => {
         let uploadTask = storageRef.child('blogs/' + this.blog.image +"-"+ moment().unix()+ "." +ext)
         try {
           uploadTask.put(blob)
           let downloadURL = uploadTask.getDownloadURL()
           this.blog.imageUrl = downloadURL
         }
         catch (error){
           console.log(error)
         }
       });
     }
   },
   save() {
     let slugify = require("slugify")
     this.blog.slug = slugify(this.blog.title)
     this.blog.user = usersCollection.doc(this.$store.state.userProfile.uid)
     this.blog.active = false
     this.blog.created = firebase.firestore.Timestamp.fromDate(new Date())
     blogsCollection.add(this.blog).then(() => {
       router.push('/admin/blogs');
     }).catch((error) => {
       console.error("Error adding document: ", error);
     });
   },
   async saveFiles(){
     await this.uploadImageFile()
     for(const fileIndex in this.files){
       let timestamp = new Date()
       let fileObject = this.files[fileIndex]
       let fileNameName = fileObject.name
       let ext = fileObject.name.split("".")[1]
       try {
         let uploadTask = storageRef.child('blogs/' + fileNameName.split("".")[0] + "-" + timestamp.getTime().toString() + "." + ext)
         await uploadTask.put(fileObject)
         let downloadURL = await uploadTask.getDownloadURL()
         this.blog.files.push({fileName:fileNameName,
           fileURL:downloadURL})
       } catch (error){
         console.log(error)
       }
     }
     this.save()
   }
}

I have assigned the @click method to the saveFiles() function.

Answer №1

Imagine you bring in the firebase library under the alias fb

Consider trying this approach:

let uploadTask = storageRef.child('blogs/' + fileNameName.split(".")[0] + "-" + timestamp.getTime().toString() + "." + ext)
await uploadTask.put(fileObject)    
fb.UploadTaskSnapshot taskSnapshot = await uploadTask.future;
Uri downloadUrl = await taskSnapshot.ref.getDownloadURL();
url1 = downloadUrl.toString();

The variable url1 will hold your downloadable URL string

Answer №2

After realizing my mistake two hours after posting the question, I discovered that the issue stemmed from a series of asynchronous functions. To resolve this, I opted to create a sequential chain of functions - starting with saveFiles, followed by uploadImage, and concluding with Save. A potential solution involved converting the cropper's content into a blob within the uploadImage function, allowing for the proper uploading process and retrieval of the image URL using async and await. Below is the revised code that successfully achieves the desired outcome.

    async saveFiles(){
      if(!this.files){
        this.uploadImageFile()
        return
      }else {
        let slugify = require("slugify")
        for (const fileIndex in this.files) {
          let timestamp = new Date()
          let fileObject = this.files[fileIndex]
          let ext = fileObject.name.split(".")[1]
          let fileNameName = slugify(fileObject.name.split(".")[0]) + "-" + 
    timestamp.getTime().toString() + "." + ext
          try {
            let uploadTask = storageRef.child('blogs/' + fileNameName)
            await uploadTask.put(fileObject)
            let downloadURL = await uploadTask.getDownloadURL()
            this.blog.files.push({
              fileName: fileNameName,
              fileURL: downloadURL
            })
          } catch (error) {
            console.log(error)
          }
        }
        //here we call the uploadImageFile
        this.uploadImageFile() 
      }
    },
    //then we have the uploadImageFile func
    uploadImageFile() {
      var slugify = require('slugify')
      let imageName = this.$refs.image.files[0].name.split(".")[0]
      let ext = this.$refs.image.files[0]['name'].split(".")[1]
      this.blog.image = slugify(imageName)+"-"+moment().unix() + "." + ext
      const {canvas} = this.$refs.cropper.getResult();
      if (canvas) {
        canvas.toBlob(blob => {
          let uploadTask = storageRef.child('blogs/' + this.blog.image ).put(blob)
          uploadTask.on('state_changed',
              (snapshot) => {
                switch (snapshot.state) {
                  case firebase.storage.TaskState.PAUSED: // or 'paused'
                    break;
                  case firebase.storage.TaskState.RUNNING: // or 'running'
                    break;
                }
              },
              (error) => {
                console.log(error);
              },
              () => {
                this.save(uploadTask)
              }
          );
        }, 'image/jpeg');
      }
      this.save()
    },
    //then we have the save
    save(uploadTask){
      let task = uploadTask.snapshot.ref.getDownloadURL();
      task.then((url)=> {
        this.blog.imageUrl = url
        let slugify = require("slugify")
        this.blog.slug = slugify(this.blog.title)
        this.blog.user = usersCollection.doc(this.$store.state.userProfile.uid)
        this.blog.active = false
        this.blog.created = firebase.firestore.Timestamp.fromDate(new Date())
        this.blog.type = this.selected
        blogsCollection.add(this.blog).then(() => {
          router.push('/admin/blogs');
        }).catch((error) => {
          console.error("Error adding document: ", error);
        });
      })
    }

With these modifications, the set of functions now operates as intended - uploading files and retrieving their respective URLs sequentially. The previous code lacked synchronization, resulting in uncompleted processes due to simultaneous operations. Here's to successful coding!

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What could be causing the position method to not provide the anticipated results?

Why is the position method not returning [left: 100, top: 10] in this particular scenario? <!DOCTYPE HTML> <html> <head> <style> #parent1 { width: 300px; height: 200px; border: solid 9px pink; } #child1 { position: ...

Angular Material's md-checkbox is a required component

I am working on a form that consists of checkboxes representing the days of the week. When the user hits submit without selecting any checkboxes, I want an error message to appear. Here is the HTML code snippet that I have: <form id="addEditForm" nam ...

Encountering a compile error with a Next.js React project that cannot be resolved

Encountered an issue while refreshing my project with the command "npm run dev" and reloading the site locally. The console displays "Compiled /not-found" and the site fails to load completely. In addition, none of the elements animated via framer motion ...

How to adjust the timezone settings in PHPMyAdmin on a shared server platform

I'm having trouble changing my timezone to India on my shared server database. I've tried everything but can't seem to get it to work. My website is built using PHP Codeigniter The contact us page on my site saves all inquiry details to my ...

Turning a string array into a basic array can be achieved through a few simple steps

While I am aware that this question has been posed multiple times, my scenario is slightly unique. Despite exhausting numerous methods, I have yet to discover a suitable workaround. $array = ["9","8","7","6","5"]; //result of javascript JSON.stringify() ...

Press on the menu <li> item to create additional submenus

A group of friends is facing a challenge. They want to create a dropdown sub-menu that appears directly below the selected item when clicking on a link from a menu. So far, they have been able to use ajax to send requests and generate a sub-menu. However, ...

Press the Radio Button to automatically submit the form in ASP.Net Core

While working with ASP.Net Core, I encountered a scenario where I needed to update the page based on the radio button that a user clicks. I wanted the page to refresh automatically to display new data depending on the selected radio button. Would it be be ...

How about this sentence: "Automatically select a radio button after verifying the associated sentence (label)

Having a bit of trouble... I'm looking to automatically click a radio button...but also need to verify the corresponding sentence (label)... eg...() <-radio button <label>What is 1+1?</label><br/> <input type="radio" name="gro ...

Are you experiencing issues with the .submit() function when used in conjunction with other

Currently, I am working on a survey form that incorporates JQuery to dynamically display or hide fields based on user selections. //FORM CONDITIONALS: This script is responsible for hiding all the helpfulness radios and only displaying them when "Yes" fo ...

Node.js environment variable returns a value of 'undefined'

One method I use to safeguard my bot tokens is by utilizing dotenv to keep them separate from the main app. However, a problem arises when running the code - the environment variables appear as undefined, resulting in an error message: Error: An invalid to ...

Tips for showing validation message just one time along with multiple error messages

Exploring ways to implement a dynamic form submit function using jQuery. $('#btnsumbit').click(function() { $('.required_field').each(function() { if ($(this).val() == "") { alert('please fill field'); ret ...

Employing ExpressJS on the server side and JQuery on the client side for handling static links

Recently delved into the world of jQuery and node.js, and everything was smooth sailing until I hit a roadblock. Despite my best efforts to search online, I couldn't find a solution to my problem. It seems like a simple issue, but I just can't fi ...

Managing time intervals and scoping challenges in a Jquery plugin

Currently, I am in the process of creating a simple JQuery plugin with a specific functionality. My goal is to pass a single element like $("div").applyPlugin(); and have it loop through each selector provided, setting an interval that is unique to that in ...

The enigmatic loop traversal

Can you figure out why the name property of the merged object is properly set in the code below, even though the for-loop starts with i = 1? function merge(root){ for ( var i = 1; i < arguments.length; i++ ){ for ( var key in arguments[i] ){ ...

I am encountering difficulties while attempting to generate the chart series in Highcharts

This is just a demonstration https://jsfiddle.net/kkulig/0k4m5d2q/ I have made some changes to the original code Swapped out the following var originalCategories = [new Category('A'), new Category('B'), new Category('C')].m ...

Having trouble getting the vue-slick-carousel to function properly when using it from the CDN

Struggling to implement a small app using the CDN script at , but so far no success. I'm a novice with vue.js and unsure if I need to import anything. According to the documentation, importing is required: Vue-slick-carousel Following this structure ...

When using firebase.firestore(), the data displayed is completely different and does not match the content of my actual database documents

I am trying to fetch data from firebase firestore using the following code: let db = firebase.firestore(); let locations = db.collection("location"); console.log("locations", locations); However, the logged data is coming back strange and not showing the ...

Guide to properly registering components in Vue.js without any errors

After importing a folder containing an index file, I am encountering this error. How can I resolve it? Root directory .app.js .store ..index.js import store from './store/index' Vue.component('posts', require('./components/Pos ...

Guide to Creating a Pop Up Image Display with Bootstrap

Can someone help me achieve the same functionality as the Fiddle linked below? http://jsfiddle.net/6CR2H/1/ I have tried to replicate it by including both external files, but the image is not displaying as a pop-up when clicked. <link href="http:// ...

Erroneous spread transformation in Babel

A question regarding the incorrect conversion/transpiling of code by Babel: const arr = [...new Set([1, 2, 3, 1])] This is being converted into: var arr = [].concat(new Set([1, 2, 3, 1])) The original code returns a list of numbers, while the transformed ...