מפעילים של אחסון בענן


אתה יכול להפעיל פונקציה בתגובה להעלאה, עדכון או מחיקה של קבצים ותיקיות ב-Cloud Storage.

דוגמאות בדף זה מבוססות על פונקציה לדוגמה המופעלת כאשר קבצי תמונה מועלים ל-Cloud Storage. פונקציה לדוגמה זו מדגימה כיצד לגשת לתכונות אירוע, כיצד להוריד קובץ למופע של Cloud Functions, ועקרונות יסוד אחרים של טיפול באירועי Cloud Storage.

ייבא את המודולים הדרושים

כדי להתחיל, ייבא את המודול הנדרש לטיפול באירועי Cloud Storage:

Node.js

 const {onObjectFinalized} = require("firebase-functions/v2/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 = 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 ולהגדיר את כל האפשרויות הרצויות:

Node.js

// scope handler to a specific bucket, using storage options parameter
export 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, עליך להוריד קבצים למופע הפונקציות - כלומר, המחשב הוירטואלי שמריץ את הקוד שלך.

באמצעות פונקציות ענן יחד עם תוכנות עיבוד תמונה כמו 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 בהתקשרות חזרה.

פִּיתוֹן

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