Reputation: 77
I'm trying to let users download images from firebase storage. Every image has it's download URL saved in a firestore collection, so when generating images each is is assigned it's correct url. Like:
<img src="https://firebasestorage.googleapis.com/v0/b/odyssey-
f90f0.appspot.com/o/images%2F2539888b-eabd-84b9-9c72-b0f1ee9b0af6?alt=media&token=acb8655f-fd8f-
4d94-9ba0-dc29c3f3c399">
Which works fine for actually getting and displaying the image. However when I try to let users download it with another link with a download attribute like:
<a href="#" download="https://firebasestorage.googleapis.com/v0/b/odyssey-
f90f0.appspot.com/o/images%2F2539888b-eabd-84b9-9c72-b0f1ee9b0af6?
alt=media&token=acb8655f-fd8f-4d94-9ba0-dc29c3f3c399">Download</a>
It just downloads some strange file format that isn't viewable:
Originally I just thought it was a CORS problem, so I followed the firebase documentation https://firebase.google.com/docs/storage/web/download-files and downloaded the gsutil command line tool, then set up a cors.json and set the CORS confirguration as follows:
[
{
"origin": ["*"],
"method": ["GET"],
"maxAgeSeconds": 3600
}
]
From there it still wasn't working so I set read on the google cloud image bucket to public and made sure my firebase storage rules were set to read for public as well. Still no change.
At this point I have really no idea what to do. Maybe there's some way to use this code (firebase documentation on how to download a file) to grab the actual file data and set it to be the download attribute rather than the url or something, but I don't know how to go about doing that.
function downloadImage(imageURL) {
// Create a reference to the file we want to download
var httpsReference = storage.refFromURL(imageURL);
// Get the download URL
httpsReference.getDownloadURL()
.then((url) => {
// download image directly via url
var xhr = new XMLHttpRequest();
xhr.responseType = 'blob';
xhr.onload = (event) => {
var blob = xhr.response;
};
xhr.open('GET', url);
xhr.send();
});
Also, strangely- if I right click an image displaying on the website, save as- and then manually set a .jpg or .png file extension or something it downloads and works. However when I add that to the code, it just downloads a file that is "not a supported format".
Any help or even pointers to resources I've missed would be really appreciated.
Upvotes: 2
Views: 3453
Reputation: 77
I was able to come up with a workaround.
<body>
<a id = 'tagID' href = '' download = ''>Download</a>
</body>
<script>
//create a reference to the image in the firebase storage by using the url
var httpsReference = storage.refFromURL(imageURL);
// Get the download URL
httpsReference.getDownloadURL()
.then((url) => {
// download image directly via url
var xhr = new XMLHttpRequest();
xhr.responseType = 'blob';
xhr.onload = (event) => {
var blob = xhr.response;
//create a file from the returned blob
var file = new File([blob], "image name", { type: blob.type });
//grab the a tag
a1 = document.getElementById('tagID');
//set the download attribute of the a tag to the name stored in the file
a1.download = file.name;
//generate a temp url to host the image for download
a1.href = URL.createObjectURL(file);
};
xhr.open('GET', url);
xhr.send();
});
</script>
Image will now download when a user clicks the anchor element.
Note: You can create the reference to storage with a direct path or with the url to google cloud as well. See the firebase docs: https://firebase.google.com/docs/storage/web/download-files
Upvotes: 4