Puoi 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 viene attivata quando i file immagine vengono caricati in Cloud Storage. Questa funzione di esempio mostra come accedere agli attributi degli eventi, come scaricare un file in un'istanza Cloud Functions e altri aspetti fondamentali della gestione degli eventi Cloud Storage.
Importa i moduli richiesti
Per iniziare, importa il modulo necessario per la gestione degli eventi Cloud Storage:
Node.js
const {onObjectFinalized} = require("firebase-functions/storage");
Python
from firebase_functions import storage_fn
Per creare l'esempio completo, aggiungi anche le dipendenze per gli strumenti di elaborazione delle immagini e Firebase Admin SDK:
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 = /** @type {SharpConstructor} */ (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
Definisci l'ambito di una funzione Cloud Storage
Utilizza il seguente pattern per limitare l'ambito della tua funzione a un bucket Cloud Storage specifico e imposta le opzioni che preferisci:
Node.js
// scope handler to a specific bucket, using storage options parameter
exports.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]):
# ...
Al contrario, la funzione di generazione delle miniature di esempio è limitata al bucket predefinito per il progetto:
Node.js
exports.generateThumbnail = onObjectFinalized({cpu: 2}, async (event) => { // ... });
Python
@storage_fn.on_object_archived()
def generatethumbnail(event: storage_fn.CloudEvent[storage_fn.StorageObjectData]):
# ...
Impostare la posizione della funzione
Una mancata corrispondenza tra le posizioni può causare un errore di deployment. 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 è uguale a quella del trigger
- La posizione della funzione si trova all'interno della posizione del trigger (quando la regione del trigger è doppia/multiregionale)
- La funzione può trovarsi in qualsiasi località se la regione del trigger è impostata su
us-central1
Gestire gli eventi Cloud Storage
Sono disponibili i seguenti gestori per rispondere agli eventi Cloud Storage:
Node.js
onObjectArchivedInviato solo quando è abilitato il controllo delle versioni degli oggetti in un bucket. Questo evento indica che la versione live di un oggetto è diventata una versione archiviata, o perché è stata archiviata o perché è stata sovrascritta dal caricamento di un oggetto con lo stesso nome.onObjectDeletedInviato quando un oggetto è stato eliminato definitivamente. Sono considerate eliminazioni definitive anche la sovrascrittura o l'eliminazione di oggetti nell'ambito della configurazione del ciclo di vita del bucket. Per i bucket con controllo delle versioni degli oggetti abilitato, non viene inviato in caso di archiviazione di un oggetto (vedionArchive), anche se l'archiviazione avviene tramite il metodostorage.objects.delete.onObjectFinalizedInviato in caso di corretta creazione di un nuovo oggetto (o di nuova generazione di un oggetto esistente) nel bucket. Sono considerate creazioni anche la copia o la riscrittura di un oggetto esistente. Questo evento non viene attivato da un caricamento non riuscito.onMetadataUpdatedInviato in caso di variazioni nei metadati di un oggetto esistente.
Python
on_object_archivedInviato solo quando è abilitato il controllo delle versioni degli oggetti in un bucket. Questo evento indica che la versione live di un oggetto è diventata una versione archiviata, o perché è stata archiviata o perché è stata sovrascritta dal caricamento di un oggetto con lo stesso nome.on_object_deletedInviato quando un oggetto è stato eliminato definitivamente. Sono considerate eliminazioni definitive anche la sovrascrittura o l'eliminazione di oggetti nell'ambito della configurazione del ciclo di vita del bucket. Per i bucket con controllo delle versioni degli oggetti abilitato, non viene inviato in caso di archiviazione di un oggetto (vedionArchive), anche se l'archiviazione avviene tramite il metodostorage.objects.delete.on_object_finalizedInviato in caso di corretta creazione di un nuovo oggetto (o di nuova generazione di un oggetto esistente) nel bucket. Sono considerate creazioni anche la copia o la riscrittura di un oggetto esistente. Questo evento non viene attivato da un caricamento non riuscito.on_metadata_updatedInviato in caso di variazioni nei metadati di un oggetto esistente.
Accedere agli attributi dell'oggetto Cloud Storage
Cloud Functions espone una serie di attributi dell'oggetto Cloud Storage
come le dimensioni e il tipo di contenuto del file aggiornato. L'attributo metageneration
viene incrementato ogni volta che vengono apportate modifiche ai
metadati dell'oggetto. Per i nuovi oggetti, il valore di 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
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."); }
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
Scaricare, trasformare e caricare un file
In alcuni casi, potrebbe non essere necessario scaricare i file da Cloud Storage. Tuttavia, per eseguire attività intensive come la generazione di un'immagine in miniatura da un file archiviato in Cloud Storage, devi 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 sui file di immagini grafiche. Di seguito è riportato un esempio di come
creare un'immagine in miniatura per un file 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 sull'istanza Cloud Functions. In questa posizione, puoi elaborare il file in base alle tue esigenze e poi caricarlo su Cloud Storage. Quando esegui attività asincrone, assicurati di restituire una promessa JavaScript nel callback.
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")
Questo codice crea una miniatura 200x200 per l'immagine salvata in una directory temporanea, quindi la carica di nuovo su Cloud Storage.