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

पूरा सैंपल बनाने के लिए, 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 का इस्तेमाल, इमेज प्रोसेस करने वाले प्रोग्राम के साथ किया जा सकता है. जैसे, Node.js के लिए sharp और Python के लिए Pillow. इससे, ग्राफ़िक वाली इमेज फ़ाइलों में बदलाव किए जा सकते हैं. अपलोड की गई इमेज फ़ाइल के लिए थंबनेल इमेज बनाने का तरीका यहां बताया गया है:

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 पर वापस अपलोड करता है.