Điều kiện kích hoạt Cloud Storage


Bạn có thể kích hoạt một hàm để phản hồi việc tải lên, cập nhật hoặc xóa tệp và thư mục trong Cloud Storage.

Các ví dụ trong trang này dựa trên một hàm mẫu kích hoạt khi hình ảnh tệp đã được tải lên Cloud Storage. Hàm mẫu này minh hoạ cách truy cập vào các thuộc tính của sự kiện, cách tải tệp xuống Cloud Functions thực thể khác và các nguyên tắc cơ bản khác để xử lý sự kiện Cloud Storage.

Nhập các mô-đun bắt buộc

Để bắt đầu, hãy nhập mô-đun cần thiết để xử lý Cloud Storage sự kiện:

Node.js

 const {onObjectFinalized} = require("firebase-functions/v2/storage");

Python

 from firebase_functions import storage_fn

Để tạo toàn bộ mẫu, bạn cũng nên thêm các phần phụ thuộc cho Firebase Admin SDK và các công cụ xử lý hình ảnh:

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

Xác định phạm vi của một hàm Cloud Storage

Sử dụng mẫu sau để đặt phạm vi vào một nhóm Cloud Storage cụ thể và đặt bất kỳ tuỳ chọn nào mong muốn:

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]):
    # ...

Ngược lại, hàm tạo hình thu nhỏ mẫu nằm trong phạm vi bộ chứa mặc định cho dự án:

Node.js

exports.generateThumbnail = onObjectFinalized({cpu: 2}, async (event) => {
// ...
});

Python

@storage_fn.on_object_archived()
def generatethumbnail(event: storage_fn.CloudEvent[storage_fn.StorageObjectData]):
    # ...

Đặt vị trí của hàm

Không khớp giữa có thể dẫn đến lỗi triển khai. Ngoài ra, khoảng cách giữa vị trí của bộ chứa Cloud Storage và vị trí của hàm có thể tạo ra đáng kể độ trễ mạng. Để tránh những trường hợp này, hãy nêu rõ vị trí hàm để khớp với vị trí nhóm/điều kiện kích hoạt theo một trong các cách sau:

  • Vị trí hàm giống với vị trí của điều kiện kích hoạt
  • Vị trí hàm nằm bên trong vị trí của điều kiện kích hoạt (khi vùng của điều kiện kích hoạt là kép/nhiều vùng)
  • Hàm có thể ở vị trí bất kỳ nếu khu vực kích hoạt được đặt thành us-central1

Xử lý các sự kiện Cloud Storage

Bạn có thể sử dụng những trình xử lý phản hồi sự kiện Cloud Storage sau đây:

Node.js

  • onObjectArchived Chỉ được gửi khi một bộ chứa đã bật tạo phiên bản đối tượng. Sự kiện này cho biết rằng phiên bản trực tiếp của một đối tượng đã trở thành một phiên bản đã lưu trữ, có thể là vì bản dịch đã được lưu trữ hoặc bị ghi đè bằng cách tải lên một đối tượng có cùng tên.
  • onObjectDeleted Được gửi khi một đối tượng đã bị xoá vĩnh viễn. Chiến dịch này bao gồm các đối tượng bị ghi đè hoặc bị xoá trong quy trình của bộ chứa cấu hình vòng đời. Đối với những bộ chứa có tạo phiên bản đối tượng đã bật, mục này sẽ không được gửi khi đối tượng được lưu trữ (xem onArchive), ngay cả khi nếu quá trình lưu trữ xảy ra thông qua phương thức storage.objects.delete.
  • onObjectFinalized Được gửi khi một đối tượng mới (hoặc thế hệ mới của một đối tượng hiện có) đã được tạo thành công trong nhóm. Điều này bao gồm việc sao chép hoặc viết lại một đối tượng hiện có. Việc tải lên không thành công sẽ không kích hoạt sự kiện này.
  • onMetadataUpdated Được gửi khi siêu dữ liệu của một đối tượng hiện có thay đổi.

Python

  • on_object_archived Chỉ được gửi khi một bộ chứa đã bật tạo phiên bản đối tượng. Sự kiện này cho biết rằng phiên bản trực tiếp của một đối tượng đã trở thành một phiên bản đã lưu trữ, có thể là vì bản dịch đã được lưu trữ hoặc bị ghi đè bằng cách tải lên một đối tượng có cùng tên.
  • on_object_deleted Được gửi khi một đối tượng đã bị xoá vĩnh viễn. Chiến dịch này bao gồm các đối tượng bị ghi đè hoặc bị xoá trong quy trình của bộ chứa cấu hình vòng đời. Đối với những bộ chứa có tạo phiên bản đối tượng đã bật, mục này sẽ không được gửi khi đối tượng được lưu trữ (xem onArchive), ngay cả khi nếu quá trình lưu trữ xảy ra thông qua phương thức storage.objects.delete.
  • on_object_finalized Được gửi khi một đối tượng mới (hoặc thế hệ mới của một đối tượng hiện có) đã được tạo thành công trong nhóm. Điều này bao gồm việc sao chép hoặc viết lại một đối tượng hiện có. Việc tải lên không thành công sẽ không kích hoạt sự kiện này.
  • on_metadata_updated Được gửi khi siêu dữ liệu của một đối tượng hiện có thay đổi.

Truy cập vào các thuộc tính đối tượng Cloud Storage

Cloud Functions hiển thị một số thuộc tính đối tượng Cloud Storage chẳng hạn như kích thước của đối tượng và loại nội dung cho tệp được cập nhật. metageneration sẽ tăng lên bất cứ khi nào có thay đổi đối với siêu dữ liệu của đối tượng. Đối với đối tượng mới, giá trị metageneration1.

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

Mẫu tạo hình thu nhỏ sử dụng một số thuộc tính trong số này để phát hiện lần thoát các trường hợp trong đó hàm trả về:

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

Tải xuống, biến đổi và tải tệp lên

Đối với một số trường hợp, có thể bạn không cần tải tệp xuống từ Cloud Storage. Tuy nhiên, để thực hiện các công việc chuyên sâu như tạo hình thu nhỏ từ một tệp được lưu trữ trong Cloud Storage, bạn cần tải xuống tệp vào thực thể hàm – tức là máy ảo chạy mã của bạn.

Sử dụng Cloud Functions cùng với các chương trình xử lý hình ảnh như sharp cho Node.js và Pillow cho Python, bạn có thể thực hiện đối với các tệp hình ảnh đồ hoạ. Sau đây là ví dụ về cách cách tạo hình thu nhỏ cho tệp hình ảnh đã tải lên:

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

Tải tệp xuống thư mục trên thực thể Cloud Functions. Ở vị trí này, bạn có thể hãy xử lý tệp nếu cần rồi tải lên Cloud Storage. Thời gian thực hiện các tác vụ không đồng bộ, hãy đảm bảo bạn trả lại lời hứa JavaScript trong .

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")

Mã này sẽ tạo một Hình thu nhỏ có kích thước 200x200 cho hình ảnh được lưu trong thư mục tạm thời, sau đó tải hình ảnh đó lên quay lại Cloud Storage.