Aktywatory Cloud Storage


Możesz aktywować funkcję w odpowiedzi na przesyłanie, aktualizowanie lub usuwanie plików i folderów w Cloud Storage.

Przykłady na tej stronie opierają się na przykładowej funkcji, która uruchamia się, gdy pliki graficzne są przesyłane do Cloud Storage. Ta przykładowa funkcja pokazuje, jak uzyskać dostęp do atrybutów zdarzeń, jak pobrać plik do instancji Cloud Functions i poznać inne podstawy obsługi zdarzeń Cloud Storage.

Zaimportuj wymagane moduły

Zacznij od zaimportowania modułu wymaganego do obsługi zdarzeń Cloud Storage:

Node.js

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

Python

 from firebase_functions import storage_fn

Aby utworzyć pełną próbkę, dodaj też zależności pakietu SDK Firebase Admin i narzędzi do przetwarzania obrazu:

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

Zakres funkcji w Cloud Storage

Użyj poniższego wzorca, aby określić zakres funkcji do określonego zasobnika Cloud Storage i ustawić wymagane opcje:

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

Z kolei przykładowa funkcja generatora miniatur jest ograniczona do domyślnego zasobnika projektu:

Node.js

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

Python

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

Ustaw lokalizację funkcji

Niezgodność między lokalizacjami może spowodować błąd wdrożenia. Poza tym odległość między lokalizacją zasobnika Cloud Storage a lokalizacją funkcji może powodować znaczne opóźnienia sieciowe. Aby uniknąć takich sytuacji, określ lokalizację funkcji w taki sposób, aby odpowiadała lokalizacji zasobnika lub aktywatora na jeden z tych sposobów:

  • Lokalizacja funkcji jest taka sama jak lokalizacja aktywatora
  • Lokalizacja funkcji znajduje się w lokalizacji aktywatora (gdy region aktywatora obejmuje dwa lub wiele regionów)
  • Funkcja może być w dowolnej lokalizacji, jeśli region aktywatora jest ustawiony na us-central1

Obsługuj zdarzenia Cloud Storage

Dostępne są te moduły obsługi odpowiadania na zdarzenia Cloud Storage:

Node.js

  • onObjectArchived Wysyłane tylko wtedy, gdy w zasobniku włączono obsługę wersji obiektu. To zdarzenie wskazuje, że aktywna wersja obiektu stała się wersją zarchiwizowaną, ponieważ została zarchiwizowana lub została zastąpiona przez przesłanie obiektu o tej samej nazwie.
  • Wysyłane, gdy obiekt został trwale usunięty. onObjectDeleted Obejmuje to obiekty, które zostały zastąpione lub usunięte w ramach konfiguracji cyklu życia zasobnika. W przypadku zasobników z włączoną obsługą wersji obiektu nie jest on wysyłany, gdy obiekt zostanie zarchiwizowany (patrz onArchive), nawet jeśli do archiwizacji nastąpi metoda storage.objects.delete.
  • onObjectFinalized Wysyłane po utworzeniu w zasobniku nowego obiektu (lub nowej generacji istniejącego obiektu). Obejmuje to skopiowanie lub ponowne zapisanie istniejącego obiektu. Zdarzenia tego nie aktywuje nieudane przesyłanie.
  • onMetadataUpdated Wysyłane, gdy zmienią się metadane istniejącego obiektu.

Python

  • on_object_archived Wysyłane tylko wtedy, gdy w zasobniku włączono obsługę wersji obiektu. To zdarzenie wskazuje, że aktywna wersja obiektu stała się wersją zarchiwizowaną, ponieważ została zarchiwizowana lub została zastąpiona przez przesłanie obiektu o tej samej nazwie.
  • Wysyłane, gdy obiekt został trwale usunięty. on_object_deleted Obejmuje to obiekty, które zostały zastąpione lub usunięte w ramach konfiguracji cyklu życia zasobnika. W przypadku zasobników z włączoną obsługą wersji obiektu nie jest on wysyłany, gdy obiekt zostanie zarchiwizowany (patrz onArchive), nawet jeśli do archiwizacji nastąpi metoda storage.objects.delete.
  • on_object_finalized Wysyłane po utworzeniu w zasobniku nowego obiektu (lub nowej generacji istniejącego obiektu). Obejmuje to skopiowanie lub ponowne zapisanie istniejącego obiektu. Zdarzenia tego nie aktywuje nieudane przesyłanie.
  • on_metadata_updated Wysyłane, gdy zmienią się metadane istniejącego obiektu.

Dostęp do atrybutów obiektów Cloud Storage

Cloud Functions ujawnia wiele atrybutów obiektu Cloud Storage, takich jak rozmiar obiektu i typ treści zaktualizowanego pliku. Wartość atrybutu metageneration zwiększa się po każdej zmianie metadanych obiektu. W przypadku nowych obiektów metageneration ma wartość 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

Przykład generowania miniatury używa niektórych z tych atrybutów do wykrywania przypadków wyjścia, w których funkcja zwraca:

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

Pobieranie, przekształcanie i przesyłanie pliku

W niektórych przypadkach pobieranie plików z Cloud Storage może nie być konieczne. Jednak w przypadku wykonywania bardziej wymagających zadań, takich jak generowanie obrazu miniatury z pliku zapisanego w Cloud Storage, trzeba pobrać pliki do instancji funkcji, czyli do maszyny wirtualnej, na której uruchomiono kod.

Korzystając z Cloud Functions w połączeniu z programami do przetwarzania obrazów, takimi jak sharp do Node.js oraz Pillow w przypadku Pythona, możesz wykonywać operacje na plikach graficznych. Oto przykład tworzenia miniatury przesyłanego pliku graficznego:

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

Pobierz plik do katalogu tymczasowego w instancji Cloud Functions. W tej lokalizacji możesz według potrzeb przetworzyć plik, a potem przesłać go do Cloud Storage. Podczas wykonywania zadań asynchronicznych pamiętaj, aby w wywołaniu zwrotnym zwrócić obietnicę JavaScriptu.

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

Ten kod tworzy miniaturę 200 x 200 dla obrazu zapisanego w katalogu tymczasowym, a potem przesyła go z powrotem do Cloud Storage.