はじめに
まずはじめに、ここで記述する方法が正攻法なのかわからないので、もっといい方法があれば教えてほしいという意味も込めて投稿しています。
問題点
最近Firebaseをさわり始めました。
Cloud Storageを使っていた際、「Cloud Storage上の特定のフォルダ内に置かれている画像を一括で取得して一覧表示させたい」ということがあった。
単純にCloud Storageに格納されているとある画像を表示させようと思ったら、下記のようにして、
- Cloud Storage 参照を作成
-
getDownloadURL()
でファイルのダウンロードURLを取得 -
<img>
のsrc
に突っ込む
という手順を取ってやればいい。
ref = firebase.storage().ref().child('img/sample.jpg');
ref.getDownloadURL().then((url) => {
document.getElementById('image').src = url;
});
しかし残念ながら、 Cloud Storage上の特定のフォルダ内に置かれているファイルのダウンロードURLを一括で取得するようなAPIは提供されていない...
解決策
方針としては、Cloud FunctionsとFirestoreを使用します。
- Cloud Storage上に画像をアップロード
- Cloud Functions経由でFirestoreに画像のパス、もしくはダウンロードURLを書き込む
- クライアントサイドからFirestoreに格納された情報からダウンロードURLを取得し、表示する
Cloud Functions
Cloud Functions for Firebase を使用すると、Firebase 機能や HTTPS リクエストによってトリガーされたイベントに応じて、バックエンド コードを自動的に実行できます。
今回はCloud Storage上にアップロードされたタイミングでCloud Functionsを実行しFirestore内に必要な情報を書き込むようにします。
Firestore
Google の柔軟でスケーラブルな NoSQL クラウド データベースを使用して、クライアント側開発とサーバー側開発のデータを保存、同期します。
データベースみたいなもので、ここへCloud Functionsから必要な情報を書き込んでいきます。
実装
とりあえずコード全体
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.writeUrl = functions.storage.object().onFinalize((object) => {
const bucketName = 'hoge.appspot.com'; // ご自身の
const filePath = object.name;
const db = admin.firestore();
db.collection('images').add({
filePath,
downloadUrl: `https://firebasestorage.googleapis.com/v0/b/${bucketName}/o/${encodeURIComponent(filePath)}?alt=media`,
}).then(() => console.log('Done')); // eslint-disable-line no-console
});
Cloud Functionsで使う関数を定義していいます。
onFinalize()
内で、ファイルのアップロードされたときの処理を記述します。
object.name
でファイルへのパスが取得できるので、これをFirestoreに書き込みます。
または、https://firebasestorage.googleapis.com/v0/b/${bucketName}/o/${encodeURIComponent(filePath)}?alt=media
で、Cloud Storage上のpublicなファイルのURLが取得できるので(Firebaseの小ネタ集 - Qiita)、これをFirestoreに書き込みます。
あとは一覧表示したいときに、Firestoreの(上記の例では)images
コレクションを取得してきて、ドキュメント分ループさせて、はじめに記述したようにfilePath
からダウンロードURLを取得して一覧表示させます。
downloadUrl
を使えばgetDownloadURL()
する必要がないのでもっと楽だと思います。
所感
これが正攻法なのかは分からないです...
Cloud Storageの画像を一覧表示するときは普通どうするものなのだろうか...