Attivatori di archiviazione cloud


È possibile attivare una funzione in risposta al caricamento, all'aggiornamento o all'eliminazione di file e cartelle in Cloud Storage.

Gli esempi in questa pagina si basano su una funzione di esempio che si attiva quando i file di immagine vengono caricati su Cloud Storage. Questa funzione di esempio dimostra come accedere agli attributi dell'evento, come scaricare un file in un'istanza Cloud Functions e altri fondamenti della gestione degli eventi Cloud Storage.

Importa i moduli richiesti

Per iniziare, importa il modulo richiesto per la gestione degli eventi Cloud Storage:

Node.js

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

Pitone

 from firebase_functions import storage_fn

Per creare l'esempio completo, aggiungi anche le dipendenze per Firebase Admin SDK e gli strumenti di elaborazione delle immagini:

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();

Pitone

 import io
import pathlib

from PIL import Image

from firebase_admin import initialize_app

initialize_app()
from firebase_admin import storage

Ambito di una funzione di archiviazione cloud

Utilizza il modello seguente per definire l'ambito della tua funzione in un bucket Cloud Storage specifico e impostare le opzioni desiderate:

Node.js

// scope handler to a specific bucket, using storage options parameter
export archivedopts = onObjectArchived({ bucket: "myBucket" }, (event) => {
  //…
});

Pitone

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

Al contrario, la funzione di generatore di miniature di esempio ha come ambito il bucket predefinito per il progetto:

Node.js

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

Pitone

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

Imposta la posizione della funzione

Una mancata corrispondenza tra le posizioni può causare un errore di distribuzione. Inoltre, la distanza tra la posizione di un bucket Cloud Storage e la posizione della funzione può creare una latenza di rete significativa. Per evitare queste situazioni, specifica la posizione della funzione in modo che corrisponda alla posizione del bucket/trigger in uno dei seguenti modi:

  • La posizione della funzione è la stessa della posizione del trigger
  • La posizione della funzione è all'interno della posizione di trigger (quando la regione di trigger è doppia/multi regione)
  • La funzione può trovarsi in qualsiasi posizione se la regione di attivazione è impostata su us-central1

Gestire gli eventi di Cloud Storage

Sono disponibili questi gestori per la risposta agli eventi Cloud Storage:

Node.js

  • onObjectArchived Inviato solo quando un bucket ha abilitato il controllo delle versioni dell'oggetto . Questo evento indica che la versione live di un oggetto è diventata una versione archiviata, perché è stata archiviata o perché è stata sovrascritta dal caricamento di un oggetto con lo stesso nome.
  • onObjectDeleted Inviato quando un oggetto è stato eliminato definitivamente. Ciò include gli oggetti che vengono sovrascritti o eliminati come parte della configurazione del ciclo di vita del bucket. Per i bucket con il controllo delle versioni degli oggetti abilitato, questo non viene inviato quando un oggetto viene archiviato (vedere onArchive ), anche se l'archiviazione avviene tramite il metodo storage.objects.delete .
  • onObjectFinalized Inviato quando un nuovo oggetto (o una nuova generazione di un oggetto esistente) viene creato con successo nel bucket. Ciò include la copia o la riscrittura di un oggetto esistente. Un caricamento non riuscito non attiva questo evento.
  • onMetadataUpdated Inviato quando i metadati di un oggetto esistente cambiano.

Pitone

  • on_object_archived Inviato solo quando un bucket ha abilitato il controllo delle versioni dell'oggetto . Questo evento indica che la versione live di un oggetto è diventata una versione archiviata, perché è stata archiviata o perché è stata sovrascritta dal caricamento di un oggetto con lo stesso nome.
  • on_object_deleted Inviato quando un oggetto è stato eliminato definitivamente. Ciò include gli oggetti che vengono sovrascritti o eliminati come parte della configurazione del ciclo di vita del bucket. Per i bucket con il controllo delle versioni degli oggetti abilitato, questo non viene inviato quando un oggetto viene archiviato (vedere onArchive ), anche se l'archiviazione avviene tramite il metodo storage.objects.delete .
  • on_object_finalized Inviato quando un nuovo oggetto (o una nuova generazione di un oggetto esistente) viene creato con successo nel bucket. Ciò include la copia o la riscrittura di un oggetto esistente. Un caricamento non riuscito non attiva questo evento.
  • on_metadata_updated Inviato quando i metadati di un oggetto esistente cambiano.

Accedi agli attributi dell'oggetto Cloud Storage

Cloud Functions espone una serie di attributi dell'oggetto Cloud Storage, come la dimensione dell'oggetto e il tipo di contenuto per il file aggiornato. L'attributo metageneration viene incrementato ogni volta che viene apportata una modifica ai metadati dell'oggetto. Per i nuovi oggetti, il valore 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.

Pitone

bucket_name = event.data.bucket
file_path = pathlib.PurePath(event.data.name)
content_type = event.data.content_type

L'esempio di generazione delle miniature utilizza alcuni di questi attributi per rilevare i casi di uscita in cui la funzione restituisce:

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

Pitone

# 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

Scarica, trasforma e carica un file

In alcuni casi potrebbe non essere necessario scaricare file da Cloud Storage. Tuttavia, per eseguire attività impegnative come la generazione di un'immagine in miniatura da un file archiviato in Cloud Storage, è necessario scaricare i file nell'istanza delle funzioni, ovvero la macchina virtuale che esegue il codice.

Utilizzando Cloud Functions insieme a programmi di elaborazione delle immagini come sharp per Node.js e Pillow per Python, puoi eseguire manipolazioni su file di immagini grafiche. Di seguito è riportato un esempio di come creare un'immagine in miniatura per un file di immagine caricato:

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

Scarica il file in una directory temporanea sulla tua istanza Cloud Functions. In questa posizione è possibile elaborare il file secondo necessità e quindi caricarlo su Cloud Storage. Quando esegui attività asincrone, assicurati di restituire una promessa JavaScript nella richiamata.

Pitone

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

Questo codice crea una miniatura 200x200 per l'immagine salvata in una directory temporanea, quindi la carica nuovamente su Cloud Storage.