Oye
Oye

Reputation: 73

Firebase storage 'getDownloadURL' is returning undefined

I'm trying to add an image to firebase storage and also add data to firestore with the image URL. The image is uploading to firebase storage, but it's not returning the URL if I use getDownloadUrl method. It gives back this error:

Uncaught TypeError: Cannot read property 'getDownloadURL' of undefined

This is how I get input and store the data:

//Add news to firestore
var storageRef = storage.ref('images');
const addNewsForm = document.querySelector('#addNewsModal');
var user = firebase.auth().currentUser;
addNewsForm?.addEventListener('submit', (e) => {
    e.preventDefault();

    //get user info
    const img = document.getElementById("uploadFile").files[0];
    const imgName = (+new Date()) + '-' + img.name;
    const metadata = { contentType: img.type };


    const title = document.getElementById("inputNewsTitle").value;
    const content = document.getElementById("inputNewsContent").value;
    const publisher = document.getElementById("inputNewsPub").value;

    if (user != null) {
        //Add Images to Firebase Storage
        // Create a child reference
        var imagesRef = storageRef.child(imgName).put(img, metadata);

        imagesRef.snapshot.storageRef.getDownloadURL().toPromise()
            .then(function(url)  {

                console.log('Image Url -> ' + url);
                // document.querySelector('#someImageTagID').src = url;


                db.collection("news").add({
                    newsImage: url,
                    newsTitle: title,
                    newsContent: content,
                    newsPublisher: publisher,
                    timestamp: firebase.firestore.FieldValue.serverTimestamp(),
                    adminUid: user.uid
                })
                    .then(function (docRef) {
                        console.log("Document written with ID: ", docRef.id);

                    })
                    .catch(function (error) {
                        console.error("Error adding document: ", error);
                    });

            }).catch(console.error);
    } else {
        console.log('User is null');
    }


});

From the above code; I first get the image input, then send it to the firebase storage. I then pass the image URL path and send it to firebase firestore.

My storage rules :

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if false;
    }
  }
}

Upvotes: 0

Views: 2167

Answers (1)

Doug Stevenson
Doug Stevenson

Reputation: 317372

You're not working with the Firebase Storage API correctly. First, this line:

var imagesRef = storageRef.child(imgName).put(img, metadata);

put() doesn't return a reference. As you can see from the API docs, it returns an UploadTask that also works like a promise. If you want to get a download URL from the uploaded file, you will need to wait until the upload is complete, then call getDownloadURL on the same reference used to upload it, as shown in the documentation. Minimally, like this:

const imageRef = storageRef.child(imgName)
imageRef.put(img, metadata)
.then(snapshot => {
    return imageRef.getDownloadURL()
    .then(url => {
        // url is the download URL
    })
})
.catch(error => {
    // deal any errors
})

Your security rules are irrelevant here, because what you're showing is for Cloud Firestore, not for Cloud Storage. They are different products with different rules. You will need to pay attention to your rules for Storage instead.

Upvotes: 1

Related Questions