Cloud Storage 触发器

您可以触发一个函数来响应 Cloud Storage 中上传、更新或删除文件和文件夹的操作。

本页中的示例基于一个在图片文件上传到 Cloud Storage 时触发的示例函数。此示例函数演示了如何访问事件特性,如何将文件下载到 Cloud Functions 实例,以及其他有关如何处理 Cloud Storage 事件的基础知识。

在发生 Cloud Storage 更改时触发函数

使用 firebase-functions/v2/storage 子软件包创建用于处理 Cloud Storage 事件的函数。根据您是要将函数范围限定在特定的 Cloud Storage 存储桶还是使用默认存储桶,请使用下列模式之一:

// scope handler to a specific bucket, using a string parameter
export archivedbucket = onObjectArchived("myBucket", (event) => {
  //…
});

// scope handler to a specific bucket, using storage options parameter
export archivedopts = onObjectArchived({ bucket: "myBucket" }, (event) => {
  //…
});

与此相对,此缩略图生成器函数的范围限定为项目的默认存储桶:

exports.generateThumbnail = onObjectFinalized({cpu: 2}, async (event) => {
  // ...
});

设置函数位置

Cloud Storage 存储桶的位置与函数位置之间的距离可能会导致严重的网络延迟。此外,位置之间的不匹配也可能会导致部署失败。为避免这些情况,请指定函数位置,使其通过以下某种方式匹配存储桶/触发器位置:

  • 函数位置与触发器位置相同
  • 函数位置位于触发器位置范围内(当触发器区域为双区域/多区域时)
  • 如果触发器区域设置为 us-central1,函数可能位于任何位置

处理 Cloud Storage 事件

Cloud Storage 支持以下事件:

响应 Cloud Storage 事件可使用以下处理程序:

  • onObjectArchived:仅在存储桶已启用对象版本控制时发送。此事件表明某个对象的当前版本已变为归档版本,原因可能是该对象已归档,或者已被新上传的同名对象覆盖。
  • onObjectDeleted:当某个对象被永久删除时发送。这包括系统根据存储桶的生命周期配置所覆盖或删除的对象。对于启用了对象版本控制的存储桶,如果某个对象已归档(请参阅 onArchive),则系统不会发送此事件,即使通过 storage.objects.delete 方法进行归档也是如此。
  • onObjectFinalized:当存储桶中成功创建了新对象(或现有对象的新实例)时发送。这包括复制或重写现有对象。上传失败不会触发此事件。
  • onMetadataUpdated:当现有对象的元数据发生更改时发送。

访问 Cloud Storage 对象特性

Cloud Functions 公开了多个 Cloud Storage 对象特性,例如已更新文件的 sizecontentType。每当对象的元数据发生变化时,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.

缩略图生成器示例使用了上述部分特性来检测要让函数返回的退出情况:

// 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.");
}

下载、转换和上传文件

在某些情况下,您可能不需要从 Cloud Storage 下载文件。但是,执行密集型任务(例如根据 Cloud Storage 中存储的文件生成缩略图)时,您需要将文件下载到函数实例(即运行代码的虚拟机)。

为了能轻松下载对象并将其重新上传到 Cloud Storage,请使用 npm install --save @google-cloud/storage 安装 Google Cloud Storage 软件包并将其导入。如需使用 JavaScript promise 来处理外部进程(例如示例中的缩略图处理任务),还应导入 child-process-promise

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

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

使用 gcs.bucket.file(filePath).download 可将文件下载到 Cloud Functions 实例的临时目录中。在此位置,您可以根据需要处理文件,然后将结果上传到 Cloud Storage。执行异步任务时,请确保在回调中返回 JavaScript promise。

示例:图片转换

可以将 Cloud Functions 函数与 ImageMagick 等图片处理程序结合使用,对图片文件执行各种操作。以下示例说明了如何为上传的图片文件创建缩略图:

// 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!");

这段代码会执行 ImageMagick 命令行程序 convert,为保存在临时目录中的图片创建大小为 200x200 的缩略图,然后将缩略图传回 Cloud Storage。

如需了解详情,请参阅完整的 Google Cloud Storage 触发器文档