Vous pouvez déclencher une fonction en réponse à l'importation, à la mise à jour ou à la suppression de fichiers et de dossiers dans Cloud Storage.
Les exemples de cette page sont basés sur un exemple de fonction qui se déclenche lorsque des fichiers image sont importés dans Cloud Storage. Cet exemple de fonction montre comment accéder aux attributs d'événement, comment télécharger un fichier dans une instance Cloud Functions et d'autres principes de base de la gestion des événements Cloud Storage.
Importer les modules requis
Pour commencer, importez le module requis pour gérer les événements Cloud Storage :
Node.js
const {onObjectFinalized} = require("firebase-functions/v2/storage");
Python
from firebase_functions import storage_fn
Pour créer l'exemple complet, ajoutez également les dépendances pour les outils Firebase Admin SDK et de traitement des images:
Node.js
const {initializeApp} = require("firebase-admin/app");
const {getStorage} = require("firebase-admin/storage");
const logger = require("firebase-functions/logger");
const path = require("path");
// library for image resizing
const sharp = require("sharp");
initializeApp();
Python
import io
import pathlib
from PIL import Image
from firebase_admin import initialize_app
initialize_app()
from firebase_admin import storage
Définir le champ d'application d'une fonction Cloud Storage
Utilisez le modèle suivant pour définir la portée de votre fonction sur un bucket Cloud Storage spécifique et définir les options souhaitées :
Node.js
// scope handler to a specific bucket, using storage options parameter
export archivedopts = onObjectArchived({ bucket: "myBucket" }, (event) => {
//…
});
Python
# Scope handler to a specific bucket using storage options parameter
@storage_fn.on_object_archived(bucket="myBucket")
def archived_bucket(event: storage_fn.CloudEvent[storage_fn.StorageObjectData]):
# ...
En revanche, l'exemple de fonction de générateur de miniatures est limité au bucket par défaut du projet:
Node.js
exports.generateThumbnail = onObjectFinalized({cpu: 2}, async (event) => { // ... });
Python
@storage_fn.on_object_archived()
def generatethumbnail(event: storage_fn.CloudEvent[storage_fn.StorageObjectData]):
# ...
Définir l'emplacement de la fonction
Une non-concordance entre les emplacements peut entraîner l'échec du déploiement. En outre, la distance entre l'emplacement d'un bucket Cloud Storage et l'emplacement de la fonction peut créer une latence réseau importante. Pour éviter ces situations, spécifiez l'emplacement de la fonction afin qu'il corresponde à l'emplacement du bucket/déclencheur de l'une des manières suivantes :
- L'emplacement de la fonction est identique à celui du déclencheur
- L'emplacement de la fonction se trouve à l'intérieur de l'emplacement du déclencheur (lorsque la région du déclencheur est birégionale/multirégionale)
- La fonction peut se trouver n'importe où si la région du déclencheur est définie sur
us-central1
.
Gérer les événements Cloud Storage
Les gestionnaires suivants permettent de répondre aux événements Cloud Storage :
Node.js
onObjectArchived
Envoyé uniquement lorsque la gestion des versions d'objets est activée sur un bucket. Cet événement indique que la version active d'un objet est devenue une version archivée, soit parce qu'elle a été archivée, soit parce qu'elle a été écrasée par l'importation d'un objet portant le même nom.onObjectDeleted
: envoyé lorsqu'un objet a été définitivement supprimé. Cela inclut les objets écrasés ou supprimés dans le cadre de la configuration du cycle de vie du bucket. Pour les buckets pour lesquels la gestion des versions d'objets est activée, cet événement n'est pas envoyé lorsqu'un objet est archivé (voironArchive
), même si l'archivage s'effectue via la méthodestorage.objects.delete
.onObjectFinalized
: envoyé lorsqu'un objet (ou une nouvelle génération d'un objet existant) est correctement créé dans le bucket. Cela inclut la copie ou la réécriture d'un objet existant. Les échecs d'importation ne génèrent pas cet événement.onMetadataUpdated
: envoyé lorsque les métadonnées d'un objet existant sont modifiées.
Python
on_object_archived
Envoyé uniquement lorsque la gestion des versions d'objets est activée sur un bucket. Cet événement indique que la version en ligne d'un objet a été archivée (soit à la suite d'un archivage, soit parce qu'elle a été remplacée lors de l'importation d'un objet portant le même nom).on_object_deleted
Envoyée lorsqu'un objet a été définitivement supprimé. Cela inclut les objets écrasés ou supprimés dans le cadre de la configuration du cycle de vie du bucket. Pour les buckets sur lesquels la gestion des versions d'objets est activée, cet événement n'est pas envoyé lorsqu'un objet est archivé (voironArchive
), même si l'archivage s'effectue via la méthodestorage.objects.delete
.on_object_finalized
: envoyé lorsqu'un objet (ou une nouvelle génération d'un objet existant) est correctement créé dans le bucket. Cela inclut la copie ou la réécriture d'un objet existant. Les échecs d'importation ne génèrent pas cet événement.on_metadata_updated
Envoyé lorsque les métadonnées d'un objet existant sont modifiées.
Accéder aux attributs de l'objet Cloud Storage
Cloud Functions expose un certain nombre d'attributs d'objet Cloud Storage, tels que la taille et le type de contenu de l'objet pour le fichier mis à jour. L'attribut metageneration
est incrémenté chaque fois que les métadonnées de l'objet sont modifiées. Pour les nouveaux objets, la valeur metageneration
est 1
.
Node.js
const fileBucket = event.data.bucket; // Storage bucket containing the file. const filePath = event.data.name; // File path in the bucket. const contentType = event.data.contentType; // File content type.
Python
bucket_name = event.data.bucket
file_path = pathlib.PurePath(event.data.name)
content_type = event.data.content_type
L'exemple de génération de miniatures utilise certains de ces attributs pour détecter les cas de sortie dans lesquels la fonction renvoie :
Node.js
// Exit if this is triggered on a file that is not an image. if (!contentType.startsWith("image/")) { return logger.log("This is not an image."); } // Exit if the image is already a thumbnail. const fileName = path.basename(filePath); if (fileName.startsWith("thumb_")) { return logger.log("Already a Thumbnail."); }
Python
# Exit if this is triggered on a file that is not an image.
if not content_type or not content_type.startswith("image/"):
print(f"This is not an image. ({content_type})")
return
# Exit if the image is already a thumbnail.
if file_path.name.startswith("thumb_"):
print("Already a thumbnail.")
return
Télécharger, transformer et importer un fichier
Dans certains cas, il n'est pas nécessaire de télécharger des fichiers à partir de Cloud Storage. Toutefois, pour effectuer des tâches intensives telles que la génération d'une image miniature à partir d'un fichier stocké dans Cloud Storage, vous devez télécharger des fichiers dans l'instance de fonctions, c'est-à-dire la machine virtuelle qui exécute votre code.
En utilisant Cloud Functions avec des programmes de traitement d'images tels que sharp
pour Node.js et Pillow pour Python, vous pouvez effectuer des manipulations sur les fichiers image graphiques. Voici un exemple de création d'une vignette pour un fichier image importé :
Node.js
/**
* When an image is uploaded in the Storage bucket,
* generate a thumbnail automatically using sharp.
*/
exports.generateThumbnail = onObjectFinalized({cpu: 2}, async (event) => {
const fileBucket = event.data.bucket; // Storage bucket containing the file.
const filePath = event.data.name; // File path in the bucket.
const contentType = event.data.contentType; // File content type.
// Exit if this is triggered on a file that is not an image.
if (!contentType.startsWith("image/")) {
return logger.log("This is not an image.");
}
// Exit if the image is already a thumbnail.
const fileName = path.basename(filePath);
if (fileName.startsWith("thumb_")) {
return logger.log("Already a Thumbnail.");
}
// Download file into memory from bucket.
const bucket = getStorage().bucket(fileBucket);
const downloadResponse = await bucket.file(filePath).download();
const imageBuffer = downloadResponse[0];
logger.log("Image downloaded!");
// Generate a thumbnail using sharp.
const thumbnailBuffer = await sharp(imageBuffer).resize({
width: 200,
height: 200,
withoutEnlargement: true,
}).toBuffer();
logger.log("Thumbnail created");
// Prefix 'thumb_' to file name.
const thumbFileName = `thumb_${fileName}`;
const thumbFilePath = path.join(path.dirname(filePath), thumbFileName);
// Upload the thumbnail.
const metadata = {contentType: contentType};
await bucket.file(thumbFilePath).save(thumbnailBuffer, {
metadata: metadata,
});
return logger.log("Thumbnail uploaded!");
});
Téléchargez le fichier dans un répertoire temporaire de votre instance Cloud Functions. Dans cet emplacement, vous pouvez traiter le fichier si nécessaire, puis l'importer dans Cloud Storage. Lorsque vous effectuez des tâches asynchrones, assurez-vous de renvoyer une promesse JavaScript dans votre rappel.
Python
@storage_fn.on_object_finalized()
def generatethumbnail(event: storage_fn.CloudEvent[storage_fn.StorageObjectData]):
"""When an image is uploaded in the Storage bucket, generate a thumbnail
automatically using Pillow."""
bucket_name = event.data.bucket
file_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.
if not content_type or not content_type.startswith("image/"):
print(f"This is not an image. ({content_type})")
return
# Exit if the image is already a thumbnail.
if file_path.name.startswith("thumb_"):
print("Already a thumbnail.")
return
bucket = 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")
Ce code crée une vignette de 200 x 200 pixels pour l'image enregistrée dans un répertoire temporaire, puis la réimporte dans Cloud Storage.