0

I am trying to make a upload function in react-js using firebase storage and firestore. I have a function that uploads the file to firebase storage and then it posts some data to firestore. I want the url of the file to go with the data that goes to firestore. So far I can only log the URL to console but I can't store it. I have looked all over online and in the firebase documentation but I can't find a way to store the URL on upload.

If you have any suggestions on things I could try, I would appreciate it :)

publishHandler = (event) => {
    event.preventDefault();
    console.log(this.state.input);
    let url = "";
    let file = this.state.input.image;
    let storageRef = firebase.storage().ref();
    let uploadTask = storageRef.child("uploads/" +file.name).put(file);
    uploadTask.on(firebase.storage.TaskEvent.STATE_CHANGED, 
        function (snapshot) {
            let progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
            console.log("upload is " + progress + " % done.");
        },
        function(error) {
            console.log("Something went wrong..." + error);
        },
        function(complete) {
            uploadTask.snapshot.ref.getDownloadURL().then(function (downloadURL) {
                console.log(downloadURL);
                // Here is where I wish I could store the downloadURL into the url variable declared earlier
                url = downloadURL;

            });
        }
        );

    // Post data to firebase.
    db.collection("hittat").doc().set({
        title: this.state.input.title,
        amount: this.state.input.amount,
        description: this.state.input.description,
        url: url;
    });

};
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • Why can't you store the URL? It seems like the point in the code where you want to store the URL is where you actually want to put your existing code that writes the document. – Doug Stevenson Mar 13 '20 at 19:21
  • Thanks for the reply Doug! So this code fails since the variable url can't be set inside the function. I guess it has to do with scope? – Bobby Rösehag Mar 13 '20 at 19:35
  • It has to do with the fact that the Firebase APIs are all asynchronous. – Doug Stevenson Mar 13 '20 at 19:39

1 Answers1

0

I'm going to see if I can find a duplicate, but wanted to give you the code you'll need to use first.

As Doug commented, any code that needs access to the download URL needs to be inside the getDownloadURL().then callback.

So in your case:

uploadTask.on(firebase.storage.TaskEvent.STATE_CHANGED, 
    function (snapshot) {
        let progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
        console.log("upload is " + progress + " % done.");
    },
    function(error) {
        console.log("Something went wrong..." + error);
    },
    function(complete) {
        uploadTask.snapshot.ref.getDownloadURL().then(function (downloadURL) {
            console.log(downloadURL);
            // Here is where I wish I could store the downloadURL into the url variable declared earlier
            url = downloadURL;

            db.collection("hittat").doc().set({
                title: this.state.input.title,
                amount: this.state.input.amount,
                description: this.state.input.description,
                url: url;
            });
        });
    });

That probably also means you don't need the url variable anymore.

Also see:

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807