يمكنك بدء وظيفة استجابةً لتحميل الملفات والمجلدات أو تعديلها أو حذفها في 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 مع برامج معالجة الصور مثل
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. فعندما بأداء مهام غير متزامنة، فتأكد من عرض وعد جافا سكريبت في معاودة الاتصال.
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")
تُنشئ هذه التعليمة البرمجية صورة مصغَّرة بحجم 200×200 للصورة المحفوظة في دليل مؤقت، ثم تحمّلها رجوع إلى Cloud Storage