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.