Cloud Storage-Trigger


Sie können eine Funktion auslösen, wenn Dateien und Ordner in Cloud Storage hochgeladen, aktualisiert oder gelöscht werden.

Die Beispiele auf dieser Seite basieren auf einer Beispielfunktion, die ausgelöst wird, wenn Bilddateien in Cloud Storage hochgeladen werden. In dieser Beispielfunktion wird gezeigt, wie Sie auf Ereignisattribute zugreifen, eine Datei in eine Cloud Functions-Instanz herunterladen und andere Grundlagen der Verarbeitung von Cloud Storage-Ereignissen.

Erforderliche Module importieren

Importiere zuerst das Modul, das für die Verarbeitung von Cloud Storage erforderlich ist Events:

Node.js

 const {onObjectFinalized} = require("firebase-functions/v2/storage");

Python

 from firebase_functions import storage_fn

Um das vollständige Beispiel zu erstellen, fügen Sie auch die Abhängigkeiten für die Firebase Admin SDK und Bildverarbeitungstools:

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

Geltungsbereich einer Cloud Storage-Funktion festlegen

Verwenden Sie das folgende Muster, um den auf einen bestimmten Cloud Storage-Bucket anwenden und die gewünschten Optionen festlegen:

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]):
    # ...

Im Gegensatz dazu bezieht sich die Beispielfunktion zum Erstellen von Miniaturansichten auf den Standard-Bucket für Projekt:

Node.js

exports.generateThumbnail = onObjectFinalized({cpu: 2}, async (event) => {
// ...
});

Python

@storage_fn.on_object_archived()
def generatethumbnail(event: storage_fn.CloudEvent[storage_fn.StorageObjectData]):
    # ...

Speicherort der Funktion festlegen

Eine Abweichung zwischen den Standorten kann zu einem Bereitstellungsfehler führen. Außerdem kann die Entfernung zwischen dem Speicherort eines Cloud Storage-Buckets und dem Speicherort der Funktion zu einer erheblichen Netzwerklatenz führen. Um solche Situationen zu vermeiden, können Sie den Speicherort der Funktion so festlegen, dass er auf eine der folgenden Arten mit dem Speicherort des Buckets/Triggers übereinstimmt:

  • Der Standort der Funktion ist mit dem Triggerstandort identisch
  • Der Standort der Funktion befindet sich innerhalb des Triggerstandorts (wenn die Triggerregion ist Dual-/Multi-Region)
  • Die Funktion kann sich an einem beliebigen Standort befinden, wenn die Triggerregion auf us-central1 festgelegt ist

Cloud Storage-Ereignisse verarbeiten

Folgende Handler sind für die Reaktion auf Cloud Storage-Ereignisse verfügbar:

Node.js

  • onObjectArchived wird nur gesendet, wenn für einen Bucket aktiviert wurde Objektversionsverwaltung. Dieses Ereignis zeigt an, dass die Live-Version eines Objekts zu einem archivierte Version, weil sie entweder archiviert oder durch den Upload eines gleichnamigen Objekts überschrieben wird.
  • onObjectDeleted Wird gesendet, wenn ein Objekt endgültig gelöscht wurde. Dies gilt auch für Objekte, die im Rahmen der Lebenszykluskonfiguration des Buckets überschrieben oder gelöscht werden. Bei Buckets mit aktivierter Objektversionsverwaltung wird dieses Ereignis nicht gesendet, wenn ein Objekt archiviert wird (siehe onArchive). Dies gilt auch, wenn die Archivierung über die Methode storage.objects.delete erfolgt.
  • onObjectFinalized Wird gesendet, wenn ein neues Objekt (oder eine neue Generation eines vorhandenen Objekt) im Bucket erstellt wird. Dazu gehört das Kopieren oder ein vorhandenes Objekt umschreiben. Ein fehlgeschlagener Upload löst dieses Ereignis nicht aus.
  • onMetadataUpdated Wird gesendet, wenn sich die Metadaten eines vorhandenen Objekts ändern.

Python

  • on_object_archived Wird nur gesendet, wenn für einen Bucket die Objektversionsverwaltung aktiviert ist. Dieses Ereignis zeigt an, dass die Live-Version eines Objekts zu einem archivierte Version, weil sie entweder archiviert oder durch den Upload eines gleichnamigen Objekts überschrieben wird.
  • on_object_deleted Wird gesendet, wenn ein Objekt endgültig gelöscht wurde. Dies gilt auch für Objekte, die im Rahmen der Lebenszykluskonfiguration des Buckets überschrieben oder gelöscht werden. Für Buckets mit Objektversionsverwaltung aktiviert ist, wird das Ereignis nicht gesendet, wenn ein Objekt archiviert wird (siehe onArchive), auch nicht Die Archivierung erfolgt über die storage.objects.delete-Methode.
  • on_object_finalized Wird gesendet, wenn ein neues Objekt (oder eine neue Generation eines vorhandenen Objekt) im Bucket erstellt wird. Dazu gehört auch das Kopieren oder ein vorhandenes Objekt umschreiben. Ein fehlgeschlagener Upload löst dieses Ereignis nicht aus.
  • on_metadata_updated Wird gesendet, wenn sich die Metadaten eines vorhandenen Objekts ändern.

Auf Cloud Storage-Objektattribute zugreifen

Cloud Functions stellt eine Reihe von Cloud Storage-Objektattributen zur Verfügung. z. B. die Größe des Objekts und den Inhaltstyp für die aktualisierte Datei. Das metageneration wird bei jeder Änderung des Werts in die Metadaten des Objekts ein. Bei neuen Objekten lautet der metageneration-Wert 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

Im Beispiel zum Generieren von Miniaturansichten werden einige dieser Attribute verwendet, um Exits zu erkennen. Fälle, in denen die Funktion Folgendes zurückgibt:

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

Datei herunterladen, umwandeln und hochladen

In manchen Fällen ist es nicht notwendig, Dateien aus Cloud Storage Wenn Sie jedoch intensive Aufgaben ausführen möchten, z. B. ein Miniaturbild aus einer in Cloud Storage gespeicherten Datei generieren, müssen Sie Dateien auf die Functions-Instanz herunterladen, also auf die virtuelle Maschine, auf der Ihr Code ausgeführt wird.

Mit Cloud Functions und Bildverarbeitungsprogrammen wie sharp für Node.js und Pillow für Python können Sie grafische Bilddateien bearbeiten. Im Folgenden finden Sie ein Beispiel dafür, wie Sie So erstellen Sie eine Miniaturansicht für eine hochgeladene Bilddatei:

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!");
});

Datei in eine temporäre Datei herunterladen auf Ihrer Cloud Functions-Instanz. Hier können Sie Folgendes tun: die Datei nach Bedarf verarbeiten und dann in Cloud Storage hochladen. Wann? Asynchrone Aufgaben ausführen, achten Sie darauf, dass Sie ein JavaScript-Promise in Ihrem Callback des Nutzers an.

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")

Mit diesem Code wird ein eine Miniaturansicht von 200 x 200 für das Bild, das in einem temporären Verzeichnis gespeichert ist, und lädt es dann hoch. Zurück zu Cloud Storage.