Firebase Storage でパーマネントリンクを発行する方法を紹介します。
Firebase Storage とセキュリティルール
Firebase Storage は大容量のデータを保存することのできるストレージです。画像ファイルや、比較的大きな (例えば数 MB もあるような) JSOM などを保存したい場合は、Firestore ではなく Firebase Storage を使うと思います。
Firebase Storage のサンプルコードを読むと、 getDownloadURL
というメソッドが登場します。
const ref = firebase.storage().ref('images/stars.jpg'); // 1. 準備
const url = await ref.getDownloadURL(); // 2. ダウンロード URL を取得する
const response = await fetch(url); // 3. URL からダウンロードして、レスポンスを得る
const image = await response.blob(); // 4. レスポンスからバイナリを得る
上記は公式サンプルコードではなく、オリジナルです。
2. ダウンロード URL を取得する
の箇所で getDownloadURL
が使われています。ここで注目して欲しいのは、この関数の戻り値が非同期であることです。ただ URL を得るだけの関数がなぜ非同期なのかというと、この操作が実際には "秘密の URL を取得するために Google のサーバで認証を行っている" からです。
ここでいう認証とは、 storage.rules
ファイルによって定義されたセキュリティルールに合致するかどうかの判定です。このファイルは Firebase プロジェクトを作ったときに作られているかも知れませんが、なければウェブ上のダッシュボードからも読み書きできます。
さて、この認証は場合によっては "お節介" かも知れません。僕の手元では 500ms-700ms ほどの時間がかかっていますが、ネットワークが遅い場合はもっとかかることもあるでしょう。とにかくダウンロード時間を短縮したい場合 (ユーザーを待たせたくない場合)、この操作をスキップすることができます。
ただし、 この操作はバケット全体に影響を与えます。 認証をスキップするということは、誰もがストレージオブジェクトをダウンロード可能になってしまうということです。それでも問題ない場合は、以下の手順を試す価値があります。あるいは、新しいバケットを作って、ダウンロードされて大丈夫なものだけをまとめることもできます。いずれにせよ、ダウンロードされて困るものがひとつでもバケットに入っている場合は、この方法を使うべきではありません。
ファイルごとにパーマネントリンクを発行したい場合は firebase-admin の Storage オブジェクトから利用可能な getSignedUrl に目一杯長い期間を設定します。詳細は割愛します。
Firebase Storage バケットを公開する
デフォルトでは、 Firebase Storage のダウンロード URL はすべて "秘密の URL" です。これがどこで決められているかというと、 IAM で決められています。
IAM を変更するには、ブラウザで ストレージブラウザ を開いて、 Firebase プロジェクトと同じ名前のプロジェクトを選択したら、一覧から (Firebase のプロジェクト名).appspot.com
という名前のバケットを開いてください。(おそらく出てくると思いますが、Firebase 側で設定が必要かも知れません)
ストレージブラウザでは "Google Cloud Storage" と呼ばれていますが、これは "Firebase Storage" のことだと読み替えてください。
権限タブに移動すると、IAM を表示したり変更したりできます。メンバー追加をクリックして、 allUsers
に対して Storage レガシーバケット閲覧者
ロールを設定してください。このロールは標準で存在する中では唯一 storage.objects.get
権限だけを含んでいます。権限については公式のドキュメントに詳しい説明があります。
↑こちらの説明は間違っており、正しくは
Storage レガシー オブジェクト読み取り
でした。
保存ボタンを押すと、バケットが誰からもダウンロード可能になります。試しに、適当なオブジェクトをダウンロードしてみましょう。 インターネットに公開 🔗
というボタンをクリックすると、パーマネントリンクを開いてくれます。(オブジェクトのヘッダによっては直接ダウンロードされることもあります)
パーマネントリンクは https://storage.googleapis.com/(Firebase プロジェクトの名前)/(オブジェクトのパス)
という URL になっています。この URL を fetch()
なりすれば、 getDownloadURL
を使わずにダウンロードすることができます。