はじめに
Firebase console から Cloud Storageへ画像等をアップロードする際、アップロードと同時にcacheなどのメタデータなども付与したいと思うことがありました。
Cloud Functions から簡単にできるだろうと思ってたけど、若干躓いてしまったのでメモしておきます。
問題点
通常、Web(クライアントサイド)からCloud Storageのデータにメタデータを付与する場合、ドキュメントにあるように、下記のようにすればよいと思います。
// Create a reference to the file whose metadata we want to change
var forestRef = storageRef.child('images/forest.jpg');
// Create file metadata to update
var newMetadata = {
cacheControl: 'public,max-age=300',
contentType: 'image/jpeg'
}
// Update metadata properties
forestRef.updateMetadata(newMetadata).then(function(metadata) {
// Updated metadata for 'images/forest.jpg' is returned in the Promise
}).catch(function(error) {
// Uh-oh, an error occurred!
});
しかし、Cloud Functionsから同じようなことをやろうとしてもできませんでした。
解決策
結論から先に記述すると以下のように実装しました。
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.setMetadata = functions.storage.object().onFinalize((object) => {
const filePath = object.name;
const { contentType } = object;
const storage = admin.storage();
const fileRef = storage.bucket().file(filePath);
const newMetadata = {
cacheControl: 'public,max-age=3600',
};
// ここでcontentTypeに応じてメタデータを変えてみたりとか
if (contentType.startsWith('image/')) {
fileRef.setMetadata(newMetadata).then(() => {
console.log('Set Metadata'); // eslint-disable-line
}).catch((err) => {
console.log(err); // eslint-disable-line
});
}
});
参照の作成
まず、Cloud FunctionsではCloud Storage内のファイルへの参照を作成する場合、
const fileRef = admin.storage().ref().child(filePath);
としても、Cloud Functionsは通常のWeb用のAPIを使えないので動きません。なので、
const fileRef = storage.bucket().file(filePath);
こうです。
メタデータのセット
参照の作成にはドキュメントにも書いてあるので特に問題はなかったのですが、問題はメタデータのセット部分です。
fileRef.updateMetadata(newMetadata);
上記のようにしてもメタデータをセットできませんでした。
正しくは下記の通りです。
fileRef.setMetadata(newMetadata);
この方法はドキュメントを探しても見つけられませんでした(探し方が足りないのか...)。
取り合えずこれでCloud Functions経由でデータアップロードと同時にメタデータをセットすることができました。
追記
@rubytomato@github さんからコメントを頂いたので追記します。
サーバーサイドの処理ではFirebase Admin SDKを使用し、クライアントサイドの処理ではFirebase SDKを使用します。
今回のようなCloud Functionsを用いたサーバーサイドの処理はこのあたりのドキュメントを読めばよさそうです。
APIs & Libraries | Node.js | Google Cloud
メタデータに関しては、指摘していただいたように下記リンク先にドキュメントがありました。
@google-cloud/storage 1.7.0 » Class: File | Node.js | Google Cloud