Cloud Storage-Trigger


Sie können als Reaktion auf das Hochladen, Aktualisieren oder Löschen von Dateien und Ordnern im Cloud Storage eine Funktion auslösen.

Die Beispiele auf dieser Seite basieren auf einer Beispielfunktion, die ausgelöst wird, wenn Bilddateien in Cloud Storage hochgeladen werden. Diese Beispielfunktion demonstriert den Zugriff auf Ereignisattribute, das Herunterladen einer Datei in eine Cloud Functions-Instanz und andere Grundlagen der Handhabung von Cloud Storage-Ereignissen.

Importieren Sie die erforderlichen Module

Importieren Sie zunächst das Modul, das für die Verarbeitung von Cloud Storage-Ereignissen erforderlich ist:

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 das Firebase Admin SDK und die Bildverarbeitungstools hinzu:

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

Umfang einer Cloud-Speicherfunktion

Verwenden Sie das folgende Muster, um Ihre Funktion auf einen bestimmten Cloud Storage-Bucket zu beschränken und alle gewünschten Optionen festzulegen:

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 ist die Beispielfunktion zum Erstellen von Miniaturansichten auf den Standard-Bucket für das Projekt beschränkt:

Node.js

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

Python

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

Legen Sie den Funktionsstandort fest

Eine Nichtübereinstimmung zwischen Standorten kann zu einem Bereitstellungsfehler führen. Außerdem kann die Entfernung zwischen dem Standort eines Cloud Storage-Buckets und dem Standort der Funktion zu erheblicher Netzwerklatenz führen. Um diese Situationen zu vermeiden, geben Sie den Funktionsspeicherort auf eine der folgenden Arten so an, dass er mit dem Bucket-/Trigger-Speicherort übereinstimmt:

  • Der Funktionsstandort ist derselbe wie der Triggerstandort
  • Der Funktionsstandort liegt innerhalb des Triggerstandorts (wenn der Triggerbereich Dual/Multi-Region ist)
  • Die Funktion kann sich an einem beliebigen Ort befinden, wenn die Triggerregion auf us-central1 eingestellt ist

Behandeln Sie Cloud Storage-Ereignisse

Diese Handler zum Reagieren auf Cloud Storage-Ereignisse sind verfügbar:

Node.js

  • onObjectArchived Wird nur gesendet, wenn ein Bucket die Objektversionierung aktiviert hat. Dieses Ereignis zeigt an, dass die Live-Version eines Objekts zu einer archivierten Version geworden ist, entweder weil sie archiviert wurde oder weil sie durch den Upload eines Objekts mit demselben Namen überschrieben wurde.
  • onObjectDeleted Wird gesendet, wenn ein Objekt dauerhaft gelöscht wurde. Dazu gehören Objekte, die im Rahmen der Lebenszykluskonfiguration des Buckets überschrieben oder gelöscht werden. Bei Buckets mit aktivierter Objektversionierung wird dies nicht gesendet, wenn ein Objekt archiviert wird (siehe onArchive ), selbst wenn die Archivierung über die Methode storage.objects.delete erfolgt.
  • onObjectFinalized Wird gesendet, wenn ein neues Objekt (oder eine neue Generation eines vorhandenen Objekts) erfolgreich im Bucket erstellt wurde. Dazu gehört das Kopieren oder Umschreiben eines vorhandenen Objekts. 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 ein Bucket die Objektversionierung aktiviert hat. Dieses Ereignis zeigt an, dass die Live-Version eines Objekts zu einer archivierten Version geworden ist, entweder weil sie archiviert wurde oder weil sie durch den Upload eines Objekts mit demselben Namen überschrieben wurde.
  • on_object_deleted Wird gesendet, wenn ein Objekt dauerhaft gelöscht wurde. Dazu gehören Objekte, die im Rahmen der Lebenszykluskonfiguration des Buckets überschrieben oder gelöscht werden. Bei Buckets mit aktivierter Objektversionierung wird dies nicht gesendet, wenn ein Objekt archiviert wird (siehe onArchive ), selbst wenn die Archivierung über die Methode storage.objects.delete erfolgt.
  • on_object_finalized Wird gesendet, wenn ein neues Objekt (oder eine neue Generation eines vorhandenen Objekts) erfolgreich im Bucket erstellt wurde. Dazu gehört das Kopieren oder Umschreiben eines vorhandenen Objekts. Ein fehlgeschlagener Upload löst dieses Ereignis nicht aus.
  • on_metadata_updated Wird gesendet, wenn sich die Metadaten eines vorhandenen Objekts ändern.

Greifen Sie auf Cloud Storage-Objektattribute zu

Cloud Functions stellt eine Reihe von Cloud Storage-Objektattributen bereit, beispielsweise die Größe des Objekts und den Inhaltstyp für die aktualisierte Datei. Das metageneration wird jedes Mal erhöht, wenn sich die Metadaten des Objekts ändern. Für neue Objekte beträgt der metageneration 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

Das Beispiel zur Erstellung von Miniaturansichten verwendet einige dieser Attribute, um Exit-Fälle zu erkennen, 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

Laden Sie eine Datei herunter, transformieren Sie sie und laden Sie sie hoch

In einigen Fällen ist es möglicherweise nicht erforderlich, Dateien aus dem Cloud-Speicher herunterzuladen. Um jedoch intensive Aufgaben wie das Generieren eines Miniaturbilds aus einer im Cloud Storage gespeicherten Datei auszuführen, müssen Sie Dateien auf die Funktionsinstanz herunterladen, also auf die virtuelle Maschine, die Ihren Code ausführt.

Durch die Verwendung von Cloud Functions zusammen mit Bildverarbeitungsprogrammen wie sharp für Node.js und Pillow für Python können Sie Manipulationen an grafischen Bilddateien durchführen. Im Folgenden finden Sie ein Beispiel für die Erstellung eines Miniaturbilds 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!");
});

Laden Sie die Datei in ein temporäres Verzeichnis auf Ihrer Cloud Functions-Instanz herunter. An diesem Ort können Sie die Datei nach Bedarf bearbeiten und dann in den Cloud-Speicher hochladen. Stellen Sie beim Ausführen asynchroner Aufgaben sicher, dass Sie in Ihrem Rückruf ein JavaScript-Versprechen zurückgeben.

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

Dieser Code erstellt ein Miniaturbild im Format 200 x 200 für das in einem temporären Verzeichnis gespeicherte Bild und lädt es dann zurück in den Cloud-Speicher hoch.