Cloud Storage ট্রিগার

Cloud Storage-এ ফাইল ও ফোল্ডার আপলোড, আপডেট বা মুছে ফেলার প্রতিক্রিয়া হিসেবে আপনি কোনও ফাংশন ট্রিগার করতে পারবেন।

এই পৃষ্ঠার উদাহরণগুলি একটি স্যাম্পেল ফাংশনের উপর ভিত্তি করে তৈরি করা হয়েছে যা Cloud Storage-এ ছবির ফাইল আপলোড করার সময় ট্রিগার করে। এই স্যাম্পেল ফাংশন দেখায় যে কীভাবে ইভেন্ট অ্যাট্রিবিউট অ্যাক্সেস করতে হয়, কীভাবে Cloud Functions ইনস্ট্যান্সে ফাইল ডাউনলোড করতে হয় এবং Cloud Storage ইভেন্ট ম্যানেজ করার অন্যান্য মৌলিক বিষয়।

প্রয়োজনীয় মডিউল ইমপোর্ট করুন

শুরু করতে, Cloud Storage ইভেন্ট ম্যানেজ করার জন্য প্রয়োজনীয় মডিউল ইম্পোর্ট করুন:

Node.js

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

Python

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

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
exports.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-এ স্টোর করা ফাইল থেকে থাম্বনেল ছবি জেনারেট করার মতো ইনটেনসিভ টাস্ক পারফর্ম করতে, আপনাকে ফাংশন ইনস্ট্যান্সে ফাইল ডাউনলোড করতে হবে— অর্থাৎ, ভার্চুয়াল মেশিন যা আপনার কোড রান করে।

Node.js-এর জন্য sharp এবং Python-এর জন্য Pillow-এর মতো ইমেজ-প্রসেসিং প্রোগ্রামের সাথে Cloud Functions ব্যবহার করে, আপনি গ্রাফিক্যাল ইমেজ ফাইলে ম্যানিপুলেশন করতে পারবেন। আপলোড করা ছবির ফাইলের জন্য কীভাবে থাম্বনেল ছবি তৈরি করতে হয় তার উদাহরণ নিচে দেওয়া হল:

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-এ আপলোড করতে পারবেন। অ্যাসিঙ্ক্রোনাস টাস্ক সম্পাদন করার সময়, আপনার কলব্যাকে জাভাস্ক্রিপ্ট প্রমিস রিটার্ন করছেন কিনা তা ভাল করে দেখে নিন।

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

এই কোডটি সাময়িক ডিরেক্টরিতে সেভ করা ছবির জন্য একটি ২০০x২০০ থাম্বনেল তৈরি করে, তারপর এটি Cloud Storage-এ আপলোড করে।