Cloud Storage を Cloud Functions で拡張する


Cloud Storage 内のファイルやフォルダのアップロード、更新、削除に応じて、関数をトリガーできます。

このページの例は、画像ファイルが Cloud Storage にアップロードされたときにトリガーされるサンプル関数に基づいています。このサンプル関数は、イベント属性にアクセスする方法、ファイルを Cloud Functions インスタンスにダウンロードする方法、Cloud Storage イベントの処理に関するその他の基礎知識を示しています。

その他の使用例については、Cloud Functions で可能な処理をご覧ください。

Cloud Storage の変更で関数をトリガーする

functions.storage を使用して、Cloud Storage イベントを処理する関数を作成します。関数のスコープを特定の Cloud Storage バケットにするか、デフォルトのバケットを使用するかに応じて、次のいずれかを使用します。

たとえば、サムネイルを生成するサンプルは、プロジェクトのデフォルトのバケットをスコープとします。

exports.firstGenGenerateThumbnail = functions.storage.object().onFinalize(async (object) => {
  // ...
});

Cloud Storage は、次のイベントをサポートしています。

  • onArchive。バケットでオブジェクトのバージョニングが有効になっている場合にのみ送信されます。このイベントは、アーカイブ化の操作または同名オブジェクトのアップロードによる上書きが原因で、オブジェクトのライブ バージョンがアーカイブ バージョンになったことを表します。
  • onDelete。オブジェクトが完全に削除された場合に送信されます。バケットのライフサイクル構成で上書き、または削除されたオブジェクトも対象になります。オブジェクトのバージョニングが有効になっているバケットでは、storage.objects.delete メソッドによりオブジェクトがアーカイブされた場合も含めて、アーカイブの発生時にはこのイベントを送信しません(onArchive 参照)。
  • onFinalize。バケットで新しいオブジェクト(または既存オブジェクトの新しい世代)が正常に作成された場合に送信されます。既存のオブジェクトのコピーまたは書き換えを行った場合にも送信されます。アップロードが失敗した場合、このイベントはトリガーされません。
  • onMetadataUpdate。既存オブジェクトのメタデータが変更された場合に送信されます。

onFinalize について上で示したように、on イベント ハンドラ内でイベントを設定します。

Cloud Storage オブジェクトの属性にアクセスする

Cloud Functions は、更新されたファイルの sizecontentType など、Cloud Storage オブジェクトのいくつかの属性を公開します。metageneration 属性は、オブジェクトのメタデータが変更されるたびに増分されます。新しいオブジェクトの場合、metageneration の値は 1 です。

const fileBucket = object.bucket; // The Storage bucket that contains the file.
const filePath = object.name; // File path in the bucket.
const contentType = object.contentType; // File content type.

サムネイル生成サンプルでは、これらの属性のいくつかを使用して、関数が返される終了ケースを検出します。

// Exit if this is triggered on a file that is not an image.
if (!contentType.startsWith('image/')) {
  return functions.logger.log('This is not an image.');
}

// Get the file name.
const fileName = path.basename(filePath);
// Exit if the image is already a thumbnail.
if (fileName.startsWith('thumb_')) {
  return functions.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 functions = require('firebase-functions/v1');
const admin = require('firebase-admin');
admin.initializeApp()
const path = require('path');

//library for resizing images
const sharp = require('sharp');

gcs.bucket.file(filePath).download を使用して、Cloud Functions インスタンスの一時ディレクトリにファイルをダウンロードします。この場所で、必要に応じてファイルを処理してから、Cloud Storage にアップロードできます。非同期タスクを実行するときは、コールバックで JavaScript Promise を返すようにしてください。

例: 画像変換

Cloud Functions を sharp などの画像処理プログラムと組み合わせて使用すると、グラフィカルな画像ファイルに対して操作を行うことができます。次に、アップロードした画像ファイルのサムネイル画像を作成する方法の例を示します。

// Download file from bucket.
const bucket = admin.storage().bucket(fileBucket);
const metadata = {
  contentType: contentType,
};
const downloadResponse = await bucket.file(filePath).download();
const imageBuffer = downloadResponse[0];
functions.logger.log("Image downloaded!");

// Generate a thumbnail using sharp.
const thumbnailBuffer = await sharp(imageBuffer).resize({
  width: 200,
  height: 200,
  withoutEnlargement: true,
}).toBuffer();
functions.logger.log("Thumbnail created");

// Upload the thumbnail with a 'thumb_' prefix.
const thumbFileName = `thumb_${fileName}`;
const thumbFilePath = path.join(path.dirname(filePath), thumbFileName);
await bucket.file(thumbFilePath).save(thumbnailBuffer, {
  metadata: metadata,
});
return functions.logger.log("Thumbnail uploaded!");

このコードは、一時ディレクトリに保存した画像のサムネイル(200x200)を作成し、それを Cloud Storage に再アップロードします。

その他の例

画像のコード変換コンテンツのモデレートEXIF メタデータの抽出など、一般的なメディア変換関数のサンプルも用意されています。その他の例の全一覧は、GitHub をご覧ください。