您可以根據 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。時間 執行非同步工作時,請務必在 回呼。
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 x 200 縮圖,然後將其上傳回 Cloud Storage。