Home > Software engineering >  Firebase: Error .getDownloadURL is not a function
Firebase: Error .getDownloadURL is not a function

Time:02-10

I want to get the link to the uploaded image with .getDownloadURL() but I end up with an error:

Uncaught (in promise) TypeError: uploadTask.snapshot.ref.getDownloadURL is not a function

If I remove .getDownloadURL() and .ref then everything works and I end up with:

Download URL Object { bytesTransferred: 120745, ... ref: {…} }

Author source code:

import {upload} from './upload'
import { initializeApp } from "firebase/app";
import 'firebase/storage'
import { getStorage, ref, uploadBytesResumable } from "firebase/storage"
// Your web app's Firebase configuration

const firebaseConfig = {
  *code Firebase*
}
const app = initializeApp(firebaseConfig)
const storage = getStorage(app)

upload('#file', {
    multi: true,
    accept: ['.png', '.jpg', '.jpeg', '.gif'], 
    onUpload(files, blocks) {
        files.forEach((file, index) => {
            const storageRef = ref(storage, `images/${file.name}`);
            const uploadTask = uploadBytesResumable(storageRef, file);

            uploadTask.on('state_changed', snapshot => {
                const percentage = ((snapshot.bytesTransferred / snapshot.totalBytes) * 100).toFixed(0)   '%'
                const block = blocks[index].querySelector('.preview-info-progress')
                block.textContent = percentage
                block.style.width = percentage
            }, error => {
                console.log(error)
            }, () => {
                uploadTask.snapshot.ref.getDownloadURL().then(url => {  // << problem
                    console.log('Download URL', url)
                })
            })
        })
    }
})

Thank you!

CodePudding user response:

You're mixing the older, namespace syntax of SDK versions 8 and before with the newer, modular syntax of SDK versions 9 and above. That won't work, so you should pick one syntax/version and stick to that.

The modular syntax for getting the download URL is:

getDownloadURL(storageRef).then(url => {
    console.log('Download URL', url)
})

Unrelated to that, I usually find the code easier to read when I use the fact that the upload task is a promise itself. With that, the code becomes:

files.forEach((file, index) => {
    const storageRef = ref(storage, `images/${file.name}`);
    const uploadTask = uploadBytesResumable(storageRef, file);

    uploadTask.on('state_changed', snapshot => {
        const percentage = ((snapshot.bytesTransferred / snapshot.totalBytes) * 100).toFixed(0)   '%'
        const block = blocks[index].querySelector('.preview-info-progress')
        block.textContent = percentage
        block.style.width = percentage
    })
    uploadTask.then(() => {
        getDownloadURL(ref).then(url => {
            console.log('Download URL', url)
        })
    })
})

And with async/await that becomes:

files.forEach((file, index) => async {
    const storageRef = ref(storage, `images/${file.name}`);
    const uploadTask = uploadBytesResumable(storageRef, file);

    uploadTask.on('state_changed', snapshot => {
        const percentage = ((snapshot.bytesTransferred / snapshot.totalBytes) * 100).toFixed(0)   '%'
        const block = blocks[index].querySelector('.preview-info-progress')
        block.textContent = percentage
        block.style.width = percentage
    })

    await uploadTask;
    const url = await getDownloadURL(ref)
    console.log('Download URL', url)
})

CodePudding user response:

This solution from the official Firebase documentation helped.

...
    onUpload(files, blocks) {
        files.forEach((file, index) => {
            const storage = getStorage();
const starsRef = ref(storage, `images/${file.name}`);

            const uploadTask = uploadBytesResumable(starsRef, file);

            uploadTask.on('state_changed', snapshot => {
                const percentage = ((snapshot.bytesTransferred / snapshot.totalBytes) * 100).toFixed(0)   '%'
                const block = blocks[index].querySelector('.preview-info-progress')
                block.textContent = percentage
                block.style.width = percentage
                
            }, error => {
                console.log(error)
            }, () => {
                getDownloadURL(starsRef)
                  .then((url) => {
                console.log('URL:', url);
                })

            })
        })
    }
})

I don't know if this is the right solution, and while it works, I'll investigate Firebase further.

  • Related