گسترش Cloud Storage با Cloud Functions

می‌توانید تابعی را در پاسخ به بارگذاری، به‌روزرسانی، یا حذف فایل‌ها و پوشه‌ها در Cloud Storage راه‌اندازی کنید.

مثال‌های این صفحه براساس تابع نمونه‌ای است که وقتی فایل‌های تصویر در Cloud Storage بارگذاری می‌شوند راه‌اندازی می‌شود. این تابع نمونه نشان می‌دهد چگونه به مشخصه‌های رویداد دسترسی پیدا کنید، چگونه فایلی را در نمونه Cloud Functions بارگیری کنید، و دیگر اصول اولیه مدیریت رویدادهای Cloud Storage.

واحدهای لازم را وارد کنید

برای شروع، واحد موردنیاز برای مدیریت رویدادهای Cloud Storage را وارد کنید:

Node.js

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

پایتون

 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 {typeof import("sharp")} */ (require("sharp"));

initializeApp();

پایتون

 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) => {
  //…
});

پایتون

# 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) => {
// ...
});

پایتون

@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 وقتی فراداده یک شیء موجود تغییر می‌کند ارسال می‌شود.

پایتون

  • 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.

پایتون

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

پایتون

# 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 بارگذاری کنید. هنگام انجام وظایف ناهمزمان، مطمئن شوید که در بازخوان خود یک وعده جاوا اسکریپت برمی‌گردانید.

پایتون

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

این کد یک ریزعکس ‫۲۰۰×۲۰۰ برای تصویر ذخیره‌شده در یک دایرکتوری موقت ایجاد می‌کند، سپس آن را به Cloud Storage بارگذاری می‌کند.