Вы можете запустить функцию в ответ на загрузку, обновление или удаление файлов и папок в Cloud Storage .
Примеры на этой странице основаны на тестовой функции, которая срабатывает при загрузке файлов изображений в Cloud Storage . Эта тестовая функция демонстрирует, как получить доступ к атрибутам события, как загрузить файл в экземпляр Cloud Functions и другие основные принципы обработки событий Cloud Storage .
Импортируйте необходимые модули.
Для начала импортируйте модуль, необходимый для обработки событий Cloud Storage :
Node.js
const {onObjectFinalized} = require("firebase-functions/storage");
Python
from firebase_functions import storage_fn
Для создания полноценного примера добавьте также зависимости для 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
Область применения функции Cloud Storage
Используйте следующий шаблон, чтобы ограничить область действия вашей функции определенным сегментом Cloud Storage и задать необходимые параметры:
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]):
# ...
В отличие от этого, пример функции генерации миниатюр ограничен областью действия стандартного сегмента проекта:
Node.js
exports.generateThumbnail = onObjectFinalized({cpu: 2}, async (event) => { // ... });
Python
@storage_fn.on_object_archived()
def generatethumbnail(event: storage_fn.CloudEvent[storage_fn.StorageObjectData]):
# ...
Укажите местоположение функции
Несоответствие местоположений может привести к сбою развертывания. Кроме того, расстояние между местоположением сегмента Cloud Storage и местоположением функции может создавать значительную задержку в сети. Чтобы избежать подобных ситуаций, укажите местоположение функции таким образом, чтобы оно соответствовало местоположению сегмента/триггера одним из следующих способов:
- Местоположение функции совпадает с местоположением триггера.
- Местоположение функции находится внутри области срабатывания (когда область срабатывания является двойной/многорегиональной).
- Функция может находиться в любом месте, если в качестве области запуска задан регион
us-central1
Обработка событий Cloud Storage
Для обработки событий в Cloud Storage доступны следующие обработчики:
Node.js
- Событие
onObjectArchivedотправляется только в том случае, если в корзине включено версионирование объектов . Это событие указывает на то, что активная версия объекта стала архивной, либо потому что она была заархивирована, либо потому что она была перезаписана при загрузке объекта с тем же именем. -
onObjectDeletedотправляется, когда объект был безвозвратно удален. Это включает объекты, которые перезаписываются или удаляются в рамках конфигурации жизненного цикла хранилища. Для хранилищ с включенным версионированием объектов это сообщение не отправляется при архивации объекта (см.onArchive), даже если архивация происходит с помощью методаstorage.objects.delete. - Событие
onObjectFinalizedотправляется, когда в хранилище успешно создан новый объект (или новое поколение существующего объекта). Это включает копирование или перезапись существующего объекта. Неудачная загрузка не вызывает это событие. -
onMetadataUpdatedотправляется при изменении метаданных существующего объекта.
Python
- Событие
on_object_archivedотправляется только в том случае, если в корзине включено версионирование объектов . Это событие указывает на то, что активная версия объекта стала архивной, либо потому что она была заархивирована, либо потому что она была перезаписана при загрузке объекта с тем же именем. -
on_object_deletedотправляется, когда объект был безвозвратно удален. Это включает объекты, которые перезаписываются или удаляются в рамках конфигурации жизненного цикла хранилища. Для хранилищ с включенным версионированием объектов это сообщение не отправляется при архивации объекта (см.onArchive), даже если архивация происходит с помощью методаstorage.objects.delete. - Событие
on_object_finalizedотправляется при успешном создании нового объекта (или нового поколения существующего объекта) в хранилище. Это включает копирование или перезапись существующего объекта. Неудачная загрузка не вызывает это событие. -
on_metadata_updated— отправляется при изменении метаданных существующего объекта.
Доступ к атрибутам объекта Cloud Storage
Cloud Functions предоставляет доступ к ряду атрибутов объектов Cloud Storage , таких как размер объекта и тип содержимого обновляемого файла. Атрибут metageneration увеличивается при каждом изменении метаданных объекта. Для новых объектов значение 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
В примере генерации миниатюр используются некоторые из этих атрибутов для определения случаев выхода из функции, когда она возвращает значение:
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
Скачать, преобразовать и загрузить файл
В некоторых случаях загрузка файлов из Cloud Storage может быть необязательной. Однако для выполнения ресурсоемких задач, таких как создание миниатюрного изображения из файла, хранящегося в Cloud Storage , необходимо загрузить файлы в экземпляр функции — то есть в виртуальную машину, на которой выполняется ваш код.
Используя Cloud Functions совместно с программами обработки изображений, такими как sharp для Node.js и Pillow для Python, вы можете выполнять манипуляции с графическими файлами изображений. Ниже приведен пример создания миниатюры для загруженного файла изображения:
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!");
});
Загрузите файл во временную директорию вашего экземпляра Cloud Functions . В этом месте вы можете обработать файл по мере необходимости, а затем загрузить его в Cloud Storage . При выполнении асинхронных задач убедитесь, что вы возвращаете промис 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")
Этот код создает миниатюру размером 200x200 пикселей для изображения, сохраненного во временной директории, а затем загружает ее обратно в Cloud Storage .