Sie können eine Funktion als Reaktion auf das Hochladen, Aktualisieren oder Löschen von Dateien und Ordnern in Cloud Storage auslösen.
Die Beispiele auf dieser Seite basieren auf einer Beispielfunktion, die ausgelöst wird, wenn Bilddateien in Cloud Storage hochgeladen werden. Diese Beispielfunktion zeigt, wie Sie auf Ereignisattribute zugreifen, eine Datei auf eine Cloud Functions-Instanz herunterladen und andere Grundlagen der Verarbeitung von Cloud Storage-Ereignissen.
Erforderliche Module importieren
Importieren Sie zuerst 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 die Firebase Admin SDK- und 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
Cloud Storage-Funktion eingrenzen
Verwenden Sie das folgende Muster, um den Bereich Ihrer 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]):
# ...
Die Beispiel-Funktion zum Generieren von Thumbnails ist dagegen 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]):
# ...
Funktionsort festlegen
Wenn die Standorte nicht übereinstimmen, kann dies zu einem Fehler bei der Bereitstellung führen. Außerdem kann die Entfernung zwischen dem Standort eines Cloud Storage-Buckets und dem Standort der Funktion zu einer erheblichen Netzwerklatenz führen. Um diese Situationen zu vermeiden, geben Sie den Funktionsstandort so an, dass er auf eine der folgenden Arten mit dem Bucket-/Triggerstandort übereinstimmt:
- Der Funktionsstandort ist derselbe wie der Triggerstandort.
- Der Funktionsstandort befindet sich innerhalb des Triggerstandorts (wenn die Triggerregion dual oder multiregional ist).
- Die Funktion kann sich an einem beliebigen Ort befinden, wenn die Triggerregion auf
us-central1
festgelegt ist.
Cloud Storage-Ereignisse verarbeiten
Die folgenden Handler für die Reaktion auf Cloud Storage-Ereignisse sind verfügbar:
Node.js
onObjectArchived
Wird nur gesendet, wenn für einen Bucket die Objektversionsverwaltung aktiviert ist. Dieses Ereignis bedeutet, dass die Live-Version eines Objekts zu einer archivierten Version geworden ist, weil sie entweder archiviert oder durch den Upload eines Objekts mit dem gleichen Namen überschrieben wurde.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. Für Buckets mit aktivierter Objektversionsverwaltung wird dieses Ereignis nicht gesendet, wenn ein Objekt archiviert wird (sieheonArchive
). Dies gilt auch, wenn die Archivierung über die Methodestorage.objects.delete
erfolgt.onObjectFinalized
Wird gesendet, wenn ein neues Objekt (oder eine neue Generation eines vorhandenen Objekts) im Bucket erfolgreich erstellt wurde. Dazu gehört auch das Kopieren oder Neuschreiben eines bestehenden 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 für einen Bucket die Objektversionsverwaltung aktiviert ist. Dieses Ereignis bedeutet, dass die Live-Version eines Objekts zu einer archivierten Version geworden ist, weil sie entweder archiviert oder durch den Upload eines Objekts mit dem gleichen Namen überschrieben wurde.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 aktivierter Objektversionsverwaltung wird dieses Ereignis nicht gesendet, wenn ein Objekt archiviert wird (sieheonArchive
). Dies gilt auch, wenn die Archivierung über die Methodestorage.objects.delete
erfolgt.on_object_finalized
Wird gesendet, wenn ein neues Objekt (oder eine neue Generation eines vorhandenen Objekts) im Bucket erfolgreich erstellt wurde. Dazu gehört auch das Kopieren oder Neuschreiben eines bestehenden Objekts. 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 wie die Größe und den Inhaltstyp des Objekts für die aktualisierte Datei bereit. Das Attribut metageneration
wird immer dann erhöht, wenn sich die Metadaten des Objekts ändern. Bei neuen Objekten ist 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 für die Miniaturbildgenerierung werden einige dieser Attribute verwendet, um Ausstiegsszenarien 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
Datei herunterladen, transformieren und hochladen
In einigen Fällen ist es möglicherweise nicht erforderlich, Dateien von Cloud Storage herunterzuladen. Für rechenintensive Aufgaben wie das Generieren eines Vorschaubilds aus einer in Cloud Storage gespeicherten Datei müssen Sie Dateien jedoch auf die Functions-Instanz herunterladen, also auf die virtuelle Maschine, auf der Ihr Code ausgeführt wird.
Mit Cloud Functions in Kombination mit 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 eine Miniaturansicht für eine hochgeladene Bilddatei erstellen:
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 in Ihrer Cloud Functions-Instanz herunter. Dort können Sie die Datei nach Bedarf verarbeiten und dann in Cloud Storage hochladen. Wenn Sie asynchrone Aufgaben ausführen, müssen Sie in Ihrem Callback ein JavaScript-Promise 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")
Mit diesem Code wird eine 200 × 200 px große Miniaturansicht für das Bild erstellt, das in einem temporären Verzeichnis gespeichert ist. Anschließend wird die Miniaturansicht wieder in Cloud Storage hochgeladen.