So I have followed the Google's official sample for creating a Cloud Storage triggered Firebase Function that will create resized thumbnails from uploaded images and upload them to the Storage as well. Here it is simplified:
exports.generateThumbnail = functions.storage.object().onChange(event => {
// get the uploaded file data (bucket, name, type...)
// return if the file is not an image or name begins with "thumb_"
// download the uploaded image in a temporary local file,
// resize it using ImageMagick
// upload it to storage with the name "thumb_<filename>"
}
However, when the new thumbnail uploads, the function gets triggered again and so forth in a loop. They have avoided that by returning if the uploaded file has a "thumb_" prefix.
You then end up with two images (the original and the thumbnail) and I want to rewrite the existing image with the thumbnail so I only have one image with the original path.
I don't know how to go about this because I don't know how to evade the reupload loop without a name change. I can delete the original image after uploading the thumbnail but the link pointing to the original image is already returned and saved in the Realtime Database (these images are profile pictures for users).
After looking at the bucket.js
documentation in the @google-cloud/storage
npm module, I have finally managed to overwrite the original file/path with the thumbnail image and also avoid the loop,
It can be done by attaching custom metadata when uploading the thumbnail, and testing for that metadata when the function triggers the next time.
I will just post the changes I made, the rest is the same as in the linked sample.
Here's the testing:
const filePath = event.data.name
const metadata = event.data.metadata
if (metadata.isThumb) {
console.log('Exiting: Already a thumbnail')
return
}
And here's the part when the spawn
promise returns:
return spawn(/* ... */)
}).then(_ => {
console.log('Thumbnail created locally.')
metadata.isThumb = true // We add custom metadata
const options = {
destination: filePath, // Destination is the same as original
metadata: { metadata: metadata }
}
// We overwrite the (bigger) original image but keep the path
return bucket.upload(/* localThumb */, options)
})
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With