Déclencheurs Cloud Storage


Vous pouvez déclencher une fonction en réponse au téléchargement, à 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 téléchargés sur Cloud Storage. Cet exemple de fonction montre comment accéder aux attributs d'événement, comment télécharger un fichier sur une instance Cloud Functions et d'autres principes fondamentaux de la gestion des événements Cloud Storage.

Importez les modules requis

Pour commencer, importez le module requis pour gérer les événements Cloud Storage :

Noeud.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 du SDK d'administration Firebase et des outils de traitement d'image :

Noeud.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

Portée d'une fonction Cloud Storage

Utilisez le modèle suivant pour étendre votre fonction à un bucket Cloud Storage spécifique et définir les options souhaitées :

Noeud.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 vignettes est limité au compartiment par défaut du projet :

Noeud.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 inadéquation entre les emplacements peut entraîner un échec de déploiement. De plus, 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 compartiment/déclencheur de l'une des manières suivantes :

  • L'emplacement de la fonction est le même que l'emplacement 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 double/multirégion)
  • La fonction peut être à n'importe quel endroit si la région de déclenchement est définie sur us-central1

Gérer les événements Cloud Storage

Ces gestionnaires permettant de répondre aux événements Cloud Storage sont disponibles :

Noeud.js

  • onObjectArchived Envoyé uniquement lorsqu'un compartiment a activé la gestion des versions d'objets . Cet événement indique que la version live 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 le téléchargement d'un objet du même nom.
  • onObjectDeleted Envoyé lorsqu'un objet a été définitivement supprimé. Cela inclut les objets qui sont écrasés ou supprimés dans le cadre de la configuration du cycle de vie du compartiment. Pour les compartiments avec la gestion des versions d'objet activée, ceci n'est pas envoyé lorsqu'un objet est archivé (voir onArchive ), même si l'archivage se produit via la méthode storage.objects.delete .
  • onObjectFinalized Envoyé lorsqu'un nouvel objet (ou une nouvelle génération d'un objet existant) est créé avec succès dans le compartiment. Cela inclut la copie ou la réécriture d'un objet existant. Un échec de téléchargement ne déclenche pas cet événement.
  • onMetadataUpdated Envoyé lorsque les métadonnées d'un objet existant changent.

Python

  • on_object_archived Envoyé uniquement lorsqu'un bucket a activé la gestion des versions d'objets . Cet événement indique que la version live 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 le téléchargement d'un objet du même nom.
  • on_object_deleted Envoyé lorsqu'un objet a été définitivement supprimé. Cela inclut les objets qui sont écrasés ou supprimés dans le cadre de la configuration du cycle de vie du compartiment. Pour les compartiments avec la gestion des versions d'objet activée, ceci n'est pas envoyé lorsqu'un objet est archivé (voir onArchive ), même si l'archivage se produit via la méthode storage.objects.delete .
  • on_object_finalized Envoyé lorsqu'un nouvel objet (ou une nouvelle génération d'un objet existant) est créé avec succès dans le bucket. Cela inclut la copie ou la réécriture d'un objet existant. Un échec de téléchargement ne déclenche pas cet événement.
  • on_metadata_updated Envoyé lorsque les métadonnées d'un objet existant changent.

Accéder aux attributs d'objet Cloud Storage

Cloud Functions expose un certain nombre d'attributs d'objet Cloud Storage, tels que la taille de l'objet et le type de contenu pour le fichier mis à jour. L'attribut metageneration est incrémenté chaque fois qu'il y a une modification dans les métadonnées de l'objet. Pour les nouveaux objets, la valeur metageneration est 1 .

Noeud.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 vignettes utilise certains de ces attributs pour détecter les cas de sortie dans lesquels la fonction renvoie :

Noeud.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 télécharger un fichier

Dans certains cas, il peut ne pas être nécessaire de télécharger des fichiers depuis Cloud Storage. Cependant, 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 sur 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 des fichiers d'images graphiques. Voici un exemple de création d'une image miniature pour un fichier image téléchargé :

Noeud.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 sur votre instance Cloud Functions. À cet emplacement, vous pouvez traiter le fichier selon vos besoins, puis le télécharger sur 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 miniature de 200 x 200 pour l'image enregistrée dans un répertoire temporaire, puis la télécharge sur Cloud Storage.