ক্লাউড স্টোরেজ ট্রিগার

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

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

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

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

নোড.জেএস

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

পাইথন

 from firebase_functions import storage_fn

সম্পূর্ণ নমুনাটি তৈরি করতে, Firebase Admin SDK এবং ইমেজ প্রসেসিং টুলগুলির জন্য প্রয়োজনীয় নির্ভরতাগুলিও যোগ করুন:

নোড.জেএস

 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 ফাংশনের পরিধি নির্ধারণ করুন

আপনার ফাংশনটিকে একটি নির্দিষ্ট Cloud Storage বাকেটে সীমাবদ্ধ করতে এবং পছন্দসই অপশন সেট করতে নিম্নলিখিত প্যাটার্নটি ব্যবহার করুন:

নোড.জেএস

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

এর বিপরীতে, উদাহরণ থাম্বনেইল জেনারেটর ফাংশনটি প্রজেক্টের ডিফল্ট বাকেটের মধ্যে সীমাবদ্ধ থাকে:

নোড.জেএস

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 ইভেন্টগুলিতে সাড়া দেওয়ার জন্য এই হ্যান্ডলারগুলি উপলব্ধ আছে:

নোড.জেএস

  • onObjectArchived Only sent when a bucket has enabled object versioning . This event indicates that the live version of an object has become an archived version, either because it was archived or because it was overwritten by the upload of an object of the same name.
  • যখন কোনো অবজেক্ট স্থায়ীভাবে মুছে ফেলা হয় তখন 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

নোড.জেএস

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

থাম্বনেইল তৈরির নমুনাটি, ফাংশনটি রিটার্ন করার ক্ষেত্রে প্রস্থান শনাক্ত করতে এই অ্যাট্রিবিউটগুলোর কয়েকটি ব্যবহার করে:

নোড.জেএস

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

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

নোড.জেএস

/**
 * 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 the file to a temporary directory on your Cloud Functions instance. In this location, you can process the file as needed and then upload to Cloud Storage . When performing asynchronous tasks, make sure you return a JavaScript promise in your callback.

পাইথন

@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 পুনরায় আপলোড করে।