Вы можете запустить функцию в ответ на загрузку, обновление или удаление файлов и папок в 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 = /** @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
Область применения функции 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_archivedOnly sent when a bucket has enabled object versioning . This event indicates that the live version of an object has become an archived version, either because it was archived or because it was overwritten by the upload of an object of the same name. -
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 .