Stay organized with collectionsSave and categorize content based on your preferences.
You can trigger a function in response to the uploading, updating, or
deleting of files and folders inCloud Storage.
Examples in this page are based on a sample function that triggers when image
files are uploaded toCloud Storage. This sample function demonstrates
how to access event attributes, how to download a file to aCloud Functionsinstance, and other fundamentals of handlingCloud Storageevents.
Import the required modules
To get started, import the module required for handlingCloud Storageevents:
To build out the full sample, also add the dependencies for theFirebaseAdmin SDKand image processing tools:
Node.js
const{initializeApp}=require("firebase-admin/app");const{getStorage}=require("firebase-admin/storage");constlogger=require("firebase-functions/logger");constpath=require("path");// library for image resizingconstsharp=require("sharp");initializeApp();
Use the following pattern to scope your
function to a specificCloud Storagebucket and set any desired options:
Node.js
// scope handler to a specific bucket, using storage options parameterexports.archivedopts=onObjectArchived({bucket:"myBucket"},(event)=>{//…});
Python
# Scope handler to a specific bucket using storage options parameter@storage_fn.on_object_archived(bucket="myBucket")defarchived_bucket(event:storage_fn.CloudEvent[storage_fn.StorageObjectData]):# ...
By contrast, the example thumbnail generator function is scoped to the default bucket for
the project:
A mismatch between
locations can result in deployment failure. Also, distance between the location
of aCloud Storagebucket and the location of the function can create significant
network latency. To avoid these situations, specify
thefunction locationso that it
matches the bucket/trigger location in one of these ways:
Function location is the same as the trigger location
Function location is inside the trigger location (when the trigger region is
dual/multi region)
Function may be in any location if the trigger region is set tous-central1
HandleCloud Storageevents
These handlers for responding toCloud Storageevents are available:
Node.js
onObjectArchivedOnly sent when a bucket has enabledobject versioning.
This event indicates that the live version of an object has become an
archived version, either because it was archived or because it was
overwritten by the upload of an object of the same name.
onObjectDeletedSent when an object has been permanently deleted. This
includes objects that are overwritten or are deleted as part of the bucket'slifecycle configuration.
For buckets withobject versioningenabled, this is not sent when an object is archived (seeonArchive), even
if archival occurs via thestorage.objects.deletemethod.
onObjectFinalizedSent when a new object (or a new generation of an
existing object) is successfully created in the bucket. This includes copying
or rewriting an existing object. A failed upload does not trigger this event.
onMetadataUpdatedSent when the metadata of an existing object changes.
Python
on_object_archivedOnly sent when a bucket has enabledobject versioning.
This event indicates that the live version of an object has become an
archived version, either because it was archived or because it was
overwritten by the upload of an object of the same name.
on_object_deletedSent when an object has been permanently deleted. This
includes objects that are overwritten or are deleted as part of the bucket'slifecycle configuration.
For buckets withobject versioningenabled, this is not sent when an object is archived (seeonArchive), even
if archival occurs via thestorage.objects.deletemethod.
on_object_finalizedSent when a new object (or a new generation of an
existing object) is successfully created in the bucket. This includes copying
or rewriting an existing object. A failed upload does not trigger this event.
on_metadata_updatedSent when the metadata of an existing object changes.
AccessCloud Storageobject attributes
Cloud Functionsexposes a number ofCloud Storageobject attributes
such as the object's size and content type for the file updated. Themetagenerationattribute is incremented whenever there's a change to the
object's metadata. For new objects, themetagenerationvalue is1.
Node.js
constfileBucket=event.data.bucket;// Storage bucket containing the file.constfilePath=event.data.name;// File path in the bucket.constcontentType=event.data.contentType;// File content type.
The thumbnail generation sample uses some of these attributes to detect exit
cases in which the function returns:
Node.js
// Exit if this is triggered on a file that is not an image.if(!contentType.startsWith("image/")){returnlogger.log("This is not an image.");}// Exit if the image is already a thumbnail.constfileName=path.basename(filePath);if(fileName.startsWith("thumb_")){returnlogger.log("Already a Thumbnail.");}
# Exit if this is triggered on a file that is not an image.ifnotcontent_typeornotcontent_type.startswith("image/"):print(f"This is not an image. ({content_type})")return# Exit if the image is already a thumbnail.iffile_path.name.startswith("thumb_"):print("Already a thumbnail.")return
For some cases, it may not be necessary to download files fromCloud Storage. However, to perform intensive tasks such as generating a
thumbnail image from a file stored inCloud Storage, you need to download
files to the functions instance—that is, the virtual machine that runs
your code.
UsingCloud Functionstogether with image-processing programs likesharpfor Node.js
andPillowfor Python,
you can perform
manipulations on graphical image files. The following is an example of how to
create a thumbnail image for an uploaded image file:
Node.js
/*** When an image is uploaded in the Storage bucket,* generate a thumbnail automatically using sharp.*/exports.generateThumbnail=onObjectFinalized({cpu:2},async(event)=>{constfileBucket=event.data.bucket;// Storage bucket containing the file.constfilePath=event.data.name;// File path in the bucket.constcontentType=event.data.contentType;// File content type.// Exit if this is triggered on a file that is not an image.if(!contentType.startsWith("image/")){returnlogger.log("This is not an image.");}// Exit if the image is already a thumbnail.constfileName=path.basename(filePath);if(fileName.startsWith("thumb_")){returnlogger.log("Already a Thumbnail.");}// Download file into memory from bucket.constbucket=getStorage().bucket(fileBucket);constdownloadResponse=awaitbucket.file(filePath).download();constimageBuffer=downloadResponse[0];logger.log("Image downloaded!");// Generate a thumbnail using sharp.constthumbnailBuffer=awaitsharp(imageBuffer).resize({width:200,height:200,withoutEnlargement:true,}).toBuffer();logger.log("Thumbnail created");// Prefix 'thumb_' to file name.constthumbFileName=`thumb_${fileName}`;constthumbFilePath=path.join(path.dirname(filePath),thumbFileName);// Upload the thumbnail.constmetadata={contentType:contentType};awaitbucket.file(thumbFilePath).save(thumbnailBuffer,{metadata:metadata,});returnlogger.log("Thumbnail uploaded!");});
Download the file to a temporary
directory on yourCloud Functionsinstance. In this location, you can
process the file as needed and then upload toCloud Storage. When
performing asynchronous tasks, make sure you return a JavaScript promise in your
callback.
Python
@storage_fn.on_object_finalized()defgeneratethumbnail(event:storage_fn.CloudEvent[storage_fn.StorageObjectData]):"""When an image is uploaded in the Storage bucket, generate a thumbnailautomatically using Pillow."""bucket_name=event.data.bucketfile_path=pathlib.PurePath(event.data.name)content_type=event.data.content_type# Exit if this is triggered on a file that is not an image.ifnotcontent_typeornotcontent_type.startswith("image/"):print(f"This is not an image. ({content_type})")return# Exit if the image is already a thumbnail.iffile_path.name.startswith("thumb_"):print("Already a thumbnail.")returnbucket=storage.bucket(bucket_name)image_blob=bucket.blob(str(file_path))image_bytes=image_blob.download_as_bytes()image=Image.open(io.BytesIO(image_bytes))image.thumbnail((200,200))thumbnail_io=io.BytesIO()image.save(thumbnail_io,format="png")thumbnail_path=file_path.parent/pathlib.PurePath(f"thumb_{file_path.stem}.png")thumbnail_blob=bucket.blob(str(thumbnail_path))thumbnail_blob.upload_from_string(thumbnail_io.getvalue(),content_type="image/png")
[[["Easy to understand","easyToUnderstand","thumb-up"],["Solved my problem","solvedMyProblem","thumb-up"],["Other","otherUp","thumb-up"]],[["Missing the information I need","missingTheInformationINeed","thumb-down"],["Too complicated / too many steps","tooComplicatedTooManySteps","thumb-down"],["Out of date","outOfDate","thumb-down"],["Samples / code issue","samplesCodeIssue","thumb-down"],["Other","otherDown","thumb-down"]],["Last updated 2025-09-05 UTC."],[],[],null,[]]