Триггеры облачного хранилища

Вы можете запустить функцию в ответ на загрузку, обновление или удаление файлов и папок в Cloud Storage .

Examples in this page are based on a sample function that triggers when image files are uploaded to Cloud Storage . This sample function demonstrates how to access event attributes, how to download a file to a Cloud Functions instance, and other fundamentals of handling Cloud Storage events.

Импортируйте необходимые модули.

Для начала импортируйте модуль, необходимый для обработки событий 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]):
    # ...

Укажите местоположение функции

A mismatch between locations can result in deployment failure. Also, distance between the location of a Cloud Storage bucket and the location of the function can create significant network latency. To avoid these situations, specify the function location so that it matches the bucket/trigger location in one of these ways:

  • Местоположение функции совпадает с местоположением триггера.
  • Местоположение функции находится внутри области срабатывания (когда область срабатывания является двойной/многорегиональной).
  • Функция может находиться в любом месте, если в качестве области запуска задан регион us-central1

Обработка событий Cloud Storage

Для обработки событий в Cloud Storage доступны следующие обработчики:

Node.js

  • onObjectArchived Only 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.
  • onObjectDeleted Sent when an object has been permanently deleted. This includes objects that are overwritten or are deleted as part of the bucket's lifecycle configuration . For buckets with object versioning enabled, this is not sent when an object is archived (see onArchive ), even if archival occurs via the storage.objects.delete method.
  • onObjectFinalized Sent when a new object (or a new generation of an existing object) is successfully created in the bucket. This includes copying or rewriting an existing object. A failed upload does not trigger this event.
  • onMetadataUpdated отправляется при изменении метаданных существующего объекта.

Python

  • on_object_archived Only 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 Sent when an object has been permanently deleted. This includes objects that are overwritten or are deleted as part of the bucket's lifecycle configuration . For buckets with object versioning enabled, this is not sent when an object is archived (see onArchive ), even if archival occurs via the storage.objects.delete method.
  • on_object_finalized Sent when a new object (or a new generation of an existing object) is successfully created in the bucket. This includes copying or rewriting an existing object. A failed upload does not trigger this event.
  • on_metadata_updated — отправляется при изменении метаданных существующего объекта.

Доступ к атрибутам объекта Cloud Storage

Cloud Functions exposes a number of Cloud Storage object attributes such as the object's size and content type for the file updated. The metageneration attribute is incremented whenever there's a change to the object's metadata. For new objects, the metageneration value is 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

Скачать, преобразовать и загрузить файл

For some cases, it may not be necessary to download files from Cloud Storage . However, to perform intensive tasks such as generating a thumbnail image from a file stored in Cloud Storage , you need to download files to the functions instance—that is, the virtual machine that runs your code.

Using Cloud Functions together with image-processing programs like sharp for Node.js and Pillow for Python, you can perform manipulations on graphical image files. The following is an example of how to create a thumbnail image for an uploaded image file:

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!");
});

Download the file to a temporary directory on your Cloud Functions instance. In this location, you can process the file as needed and then upload to Cloud Storage . When performing asynchronous tasks, make sure you return a JavaScript promise in your 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")

Этот код создает миниатюру размером 200x200 пикселей для изображения, сохраненного во временной директории, а затем загружает ее обратно в Cloud Storage .