ทริกเกอร์ Cloud Storage


คุณทริกเกอร์ฟังก์ชันเพื่อตอบสนองต่อการอัปโหลด อัปเดต หรือลบไฟล์และโฟลเดอร์ใน Cloud Storage ได้

ตัวอย่างในหน้านี้อิงตามฟังก์ชันตัวอย่างที่ทริกเกอร์เมื่อมีการอัปโหลดไฟล์ภาพไปยัง Cloud Storage ฟังก์ชันตัวอย่างนี้แสดงวิธีเข้าถึงแอตทริบิวต์เหตุการณ์ วิธีดาวน์โหลดไฟล์ไปยังอินสแตนซ์ Cloud Functions และข้อมูลพื้นฐานอื่นๆ เกี่ยวกับการจัดการเหตุการณ์ Cloud Storage

นำเข้าโมดูลที่จำเป็น

หากต้องการเริ่มต้นใช้งาน ให้นำเข้าโมดูลที่จำเป็นสำหรับการจัดการเหตุการณ์ Cloud Storage ดังนี้

Node.js

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

Python

 from firebase_functions import storage_fn

หากต้องการสร้างตัวอย่างแบบเต็ม ให้เพิ่มทรัพยากร Dependency สำหรับ 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
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]):
    # ...

ในทางตรงกันข้าม ฟังก์ชันการสร้างภาพปกตัวอย่างจะกําหนดขอบเขตไว้ที่ที่เก็บข้อมูลเริ่มต้นของโปรเจ็กต์ ดังนี้

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

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