Pemicu Cloud Storage


Anda dapat memicu fungsi sebagai respons terhadap upload, pembaruan, atau penghapusan file dan folder di Cloud Storage.

Contoh di halaman ini didasarkan pada fungsi contoh yang dipicu saat file gambar diupload ke Cloud Storage. Fungsi contoh ini menunjukkan cara mengakses atribut peristiwa, cara mendownload file ke instance Cloud Functions, dan hal mendasar lainnya terkait penanganan peristiwa Cloud Storage.

Mengimpor modul yang diperlukan

Untuk memulai, impor modul yang diperlukan untuk menangani peristiwa Cloud Storage:

Node.js

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

Python (pratinjau)

 from firebase_functions import storage_fn

Untuk membuat contoh lengkap, tambahkan juga dependensi untuk Firebase Admin SDK dan alat pemrosesan image:

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 (pratinjau)

 import io
import pathlib

from PIL import Image

from firebase_admin import initialize_app

initialize_app()
from firebase_admin import storage

Mencakup fungsi Cloud Storage

Gunakan pola berikut untuk menentukan cakupan fungsi Anda di bucket Cloud Storage tertentu dan menetapkan opsi yang diinginkan:

Node.js

// scope handler to a specific bucket, using storage options parameter
export archivedopts = onObjectArchived({ bucket: "myBucket" }, (event) => {
  //…
});

Python (pratinjau)

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

Sebaliknya, contoh fungsi generator thumbnail tercakup dalam bucket default untuk project tersebut:

Node.js

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

Python (pratinjau)

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

Menetapkan lokasi fungsi

Ketidakcocokan antara lokasi dapat mengakibatkan kegagalan deployment. Jadi, jarak antara lokasi bucket Cloud Storage dan lokasi fungsi dapat menghasilkan latensi jaringan yang signifikan. Untuk menghindari situasi tersebut, tentukan lokasi fungsi sehingga cocok dengan lokasi bucket/pemicu melalui salah satu cara berikut:

  • Lokasi fungsi sama dengan lokasi pemicu
  • Lokasi fungsi berada di dalam lokasi pemicu (saat region pemicu berupa region ganda/multiregion)
  • Fungsi dapat berada di lokasi mana pun jika region pemicu ditetapkan ke us-central1

Menangani peristiwa Cloud Storage

Pengendali berikut tersedia untuk merespons peristiwa Cloud Storage:

Node.js

  • onObjectArchived Hanya dikirim saat bucket telah mengaktifkan pembuatan versi objek. Peristiwa ini menunjukkan bahwa versi aktif sebuah objek telah menjadi versi yang diarsipkan, baik karena versi tersebut memang telah diarsipkan maupun karena sudah ditimpa oleh objek yang diupload dengan nama yang sama.
  • onObjectDeleted Dikirim saat sebuah objek telah dihapus secara permanen. Ini mencakup objek yang ditimpa atau dihapus sebagai bagian dari konfigurasi siklus proses bucket. Untuk bucket yang telah mengaktifkan pembuatan versi objek, peristiwa ini tidak akan dikirim saat objek diarsipkan (lihat onArchive), meskipun pengarsipan terjadi melalui metode storage.objects.delete.
  • onObjectFinalized Dikirim saat objek baru (atau pembuatan ulang objek yang sudah ada) berhasil dibuat dalam bucket. Hal ini meliputi penyalinan atau penulisan ulang objek yang sudah ada. Peristiwa ini tidak akan terpicu oleh upload yang gagal.
  • onMetadataUpdated Dikirim saat terjadi perubahan terhadap metadata objek yang ada.

Python (pratinjau)

  • on_object_archived Hanya dikirim saat bucket telah mengaktifkan pembuatan versi objek. Peristiwa ini menunjukkan bahwa versi aktif sebuah objek telah menjadi versi yang diarsipkan, baik karena versi tersebut memang telah diarsipkan maupun karena sudah ditimpa oleh objek yang diupload dengan nama yang sama.
  • on_object_deleted Dikirim saat sebuah objek telah dihapus secara permanen. Ini mencakup objek yang ditimpa atau dihapus sebagai bagian dari konfigurasi siklus proses bucket. Untuk bucket yang telah mengaktifkan pembuatan versi objek, peristiwa ini tidak akan dikirim saat objek diarsipkan (lihat onArchive), meskipun pengarsipan terjadi melalui metode storage.objects.delete.
  • on_object_finalized Dikirim saat objek baru (atau pembuatan ulang objek yang sudah ada) berhasil dibuat dalam bucket. Hal ini meliputi penyalinan atau penulisan ulang objek yang sudah ada. Peristiwa ini tidak akan terpicu oleh upload yang gagal.
  • on_metadata_updated Dikirim saat terjadi perubahan terhadap metadata objek yang ada.

Mengakses atribut objek Cloud Storage

Cloud Functions menampilkan sejumlah atribut objek Cloud Storage, seperti ukuran dan jenis konten objek untuk file yang diperbarui. Atribut metageneration bertambah setiap kali terjadi perubahan pada metadata objek. Untuk objek baru, nilai metageneration adalah 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 (pratinjau)

bucket_name = event.data.bucket
file_path = pathlib.PurePath(event.data.name)
content_type = event.data.content_type

Contoh pembuatan thumbnail ini menggunakan sejumlah atribut tersebut untuk mendeteksi kasus keluar. Dalam kasus tersebut, fungsi menampilkan:

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 (pratinjau)

# 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

Mendownload, mentransformasi, dan mengupload file

Untuk beberapa kasus, mendownload file dari Cloud Storage mungkin tidak diperlukan. Namun, untuk melakukan tugas intensif, seperti membuat gambar thumbnail dari file yang disimpan di Cloud Storage, Anda harus mendownload file ke instance fungsi—yakni, mesin virtual yang menjalankan kode Anda.

Dengan menggunakan Cloud Functions bersama dengan program pemrosesan gambar, seperti sharp untuk Node.js dan Pillow untuk Python, Anda dapat melakukan manipulasi pada file gambar grafis. Berikut ini adalah contoh cara membuat gambar thumbnail untuk file gambar yang diupload:

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 file ke direktori sementara pada instance Cloud Functions Anda. Di lokasi ini, Anda dapat memproses file sesuai kebutuhan, kemudian menguploadnya ke Cloud Storage. Saat melakukan tugas asinkron, pastikan untuk menampilkan promise JavaScript di callback Anda.

Python (pratinjau)

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


Kode ini menghasilkan thumbnail berukuran 200x200 untuk gambar yang disimpan di direktori sementara, lalu menguploadnya kembali ke Cloud Storage.