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 są oparte na przykładowej funkcji, która jest uruchamiana, gdy pliki obrazów są przesyłane do Cloud Storage. Ta przykładowa funkcja pokazuje, jak uzyskać dostęp do atrybutów zdarzenia, pobrać plik do instancji Cloud Functions i wykonać inne podstawowe czynności związane z obsługą zdarzeń Cloud Storage.
Zaimportuj wymagane moduły.
Aby rozpocząć, zaimportuj moduł wymagany 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łny przykład, dodaj też zależności narzędzi Firebase Admin SDK i do przetwarzania obrazów:
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
Określanie zakresu funkcji Cloud Storage
Aby ograniczyć zakres funkcji do konkretnego zasobnika Cloud Storage i ustawić dowolne opcje, użyj tego wzorca:
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 funkcja generatora miniatur w przykładzie jest ograniczona do domyślnego zasobnika w projekcie:
Node.js
exports.generateThumbnail = onObjectFinalized({cpu: 2}, async (event) => { // ... });
Python
@storage_fn.on_object_archived()
def generatethumbnail(event: storage_fn.CloudEvent[storage_fn.StorageObjectData]):
# ...
Ustawianie lokalizacji funkcji
Niezgodność lokalizacji może spowodować niepowodzenie wdrożenia. Odległość między lokalizacją zasobnika Cloud Storage a lokalizacją funkcji może też powodować znaczne opóźnienia sieci. Aby uniknąć takich sytuacji, określ lokalizację funkcji, tak aby była zgodna z lokalizacją zasobnika lub wyzwalacza w jeden z tych sposobów:
- Lokalizacja funkcji jest taka sama jak lokalizacja wyzwalacza
- Lokalizacja funkcji znajduje się w lokalizacji aktywatora (gdy region aktywatora jest regionem podwójnym lub wieloregionowym).
- Funkcja może znajdować się w dowolnym miejscu, jeśli region wyzwalania jest ustawiony na
us-central1
Obsługa zdarzeń Cloud Storage
Dostępne są te moduły obsługi zdarzeń Cloud Storage:
Node.js
onObjectArchived
Wysyłane tylko wtedy, gdy w zasobniku jest włączona obsługa wersji obiektów. To zdarzenie wskazuje, że bieżąca wersja obiektu stała się wersją archiwalną – została zarchiwizowana albo zastąpiona przez przesłany obiekt o tej samej nazwie.onObjectDeleted
Wysyłane po trwałym usunięciu obiektu. Dotyczy to obiektów, 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 obiektów nie jest wysyłane, gdy obiekt zostanie zarchiwizowany (patrzonArchive
), nawet jeśli archiwizacja nastąpi metodą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 po zmianie metadanych istniejącego obiektu.
Python
on_object_archived
Wysyłane tylko wtedy, gdy w zasobniku jest włączona obsługa wersji obiektów. To zdarzenie wskazuje, że bieżąca wersja obiektu stała się wersją archiwalną – została zarchiwizowana albo zastąpiona przez przesłany obiekt o tej samej nazwie.on_object_deleted
Wysyłane po trwałym usunięciu obiektu. Dotyczy to obiektów, 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 obiektów nie jest wysyłane, gdy obiekt zostanie zarchiwizowany (patrzonArchive
), nawet jeśli archiwizacja nastąpi metodą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 po zmianie metadanych istniejącego obiektu.
Dostęp do atrybutów obiektu Cloud Storage
Cloud Functions udostępnia szereg atrybutów obiektu Cloud Storage, takich jak rozmiar obiektu i typ treści zaktualizowanego pliku. Atrybut metageneration
jest zwiększany za każdym razem, gdy zmieniają się metadane obiektu. W przypadku nowych obiektów wartość metageneration
to 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ładowy kod generujący 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. Aby jednak wykonywać zadania wymagające dużej ilości zasobów, takie jak generowanie miniatury z pliku przechowywanego w Cloud Storage, musisz pobrać pliki do instancji funkcji, czyli maszyny wirtualnej, na której działa Twój kod.
Używając Cloud Functions w połączeniu z programami do przetwarzania obrazów, takimi jak sharp
dla Node.js i Pillow dla Pythona, możesz manipulować plikami obrazów graficznych. Poniżej znajdziesz przykład tworzenia miniatury przesłanego pliku obrazu:
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 tymczasowego katalogu na instancji Cloud Functions. W tym miejscu możesz przetworzyć plik w razie potrzeby, a następnie przesłać go do Cloud Storage. Podczas wykonywania zadań asynchronicznych w funkcji zwrotnej zwróć obietnicę JavaScript.
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ę o wymiarach 200 x 200 dla obrazu zapisanego w katalogu tymczasowym, a następnie przesyła ją z powrotem do Cloud Storage.