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 di 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/v2/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 = 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
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]):
# ...
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/multi-regione)
- La funzione può trovarsi in qualsiasi posizione 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
onObjectArchived
Inviato solo quando è abilitato il controllo delle versioni degli oggetti nel 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.onObjectDeleted
Inviato 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
.onObjectFinalized
Inviato 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.onMetadataUpdated
Inviato in caso di variazioni nei metadati di un oggetto esistente.
Python
on_object_archived
Inviato solo quando è abilitato il controllo delle versioni degli oggetti nel 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_deleted
Inviato 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_finalized
Inviato 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_updated
Inviato 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 contenuti 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 200 x 200 per l'immagine salvata in una directory temporanea, quindi la carica di nuovo su Cloud Storage.