画像などのメディアファイルを保存できるStorageについてのメモ。
先にFirestoreの操作を把握していると理解しやすいと思う。
※Firebaseの覚書は連番付けていますが内容は続いていません。
リファレンスとクラス図
Storageにはドキュメントという概念はなく、リファレンスが主体になっている。

ストレージの取得と参照の作成
V9
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | // V9: ストレージサービスへの参照を取得 import { getStorage } from 'firebase/storage' ; const storage = getStorage(); // V9: ストレージの参照を作成 const storageRef = ref(storage); // V9: imagesディレクトリの参照 const storageRef = ref(storage, 'images' ); // V9: imagesディレクトリにある画像ファイルの参照 const storageRef = ref(storage, 'images/stars.jpg' ); // V9: Google Cloud Storage URI から参照を作成する const gsReference = ref(storage, 'gs://bucket/images/stars.jpg' ); // V9: HTTPS URL から参照を作成する(URLはエスケープ処理が必要) const httpsReference = ref(storage, 'https://firebasestorage.googleapis.com/b/bucket/o/images%20stars.jpg' ); |
V8
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | // V8: ストレージサービスへの参照を取得 const storage = firebase.storage(); // V8: ストレージの参照を作成 const storageRef = storage.ref(); // V8: imagesディレクトリの参照 const imagesRef = storageRef.child( 'images' ); // V8: imagesディレクトリにある画像ファイルの参照 const spaceRef = storageRef.child( 'images/stars.jpg' ); // V8: Google Cloud Storage URI から参照を作成する const gsReference = storage.refFromURL( 'gs://bucket/images/stars.jpg' ); // V8: HTTPS URL から参照を作成する(URLはエスケープ処理が必要) const httpsReference = storage.refFromURL( 'https://firebasestorage.googleapis.com/b/bucket/o/images%20stars.jpg' ); |
ファイルリストの取得
list()
かlistAll()
を使用する。listAll
は全ファイルを取得するので、内容が小さいディレクトリ用。list()
はページ分割に対応できるので、内容が大きいディレクトリ用である。
V9
1 2 3 4 5 | import { getStorage, ref, listAll } from "firebase/storage" ; const storage = getStorage(); const listRef = ref(storage, 'images' ); const imagesList = await listAll(listRef); |
V8
1 | const imagesList = await storageRef.child( 'images' ).listAll(); |
セキュリティールールのエラー
セキュリティルールがバージョン1だからlist(listAll)は使えねーよと怒られた場合、
Listing objects in a bucket is disallowed for rules_version = “1”.
Reference.list() Error Message
Please update storage security rules to rules_version = “2” to use list.
Storageのルールの先頭行にバージョンを明記すれば2系に変わる。
1 | rules_version = '2' ; |
list()
とlistAll()
の戻り値であるListResultにはitems
とprefixes
プロパティがあるが、それぞれ参照先が異なる。
Storageの構造が以下のようになっている場合、
1 2 3 | images/icon/arrow.png images/banner/1.png images/main.png |
items
にはimages直下にあるファイルの参照、prefixes
にはサブディレクトリの参照が配列で格納される。
1 2 3 4 5 6 7 8 9 | imagesList { items: [ Reference { name: 'main.png' } ], prefixes: [ Reference { name: 'icon' }, Reference { name: 'banner' } ] } |
ファイルのダウンロードURLを取得する
ファイルのURLはgetDownloadURL()で得られる。
getDownloadURL()はPromiseを返すので、Promise.allでおk。
ファイル単体
1 2 3 4 5 6 7 8 9 10 11 12 13 | // V9 import { getStorage, ref, listAll } from "firebase/storage" ; const storage = getStorage(); const imageRef = ref(storage, 'images/stars.jpg' ); getDownloadURL(imageRef) .then((url) => { // `url` is the download URL for 'images/stars.jpg' }) . catch ((error) => { // Handle any errors }); |
listAllの場合
V9
1 2 3 4 5 6 7 8 9 | import { getStorage, ref, listAll } from "firebase/storage" ; const storage = getStorage(); const listRef = ref(storage, 'images' ); const imagesList = await listAll(listRef); const urls = await Promise.all( imagesList.items.map(ref => getDownloadURL(ref)) ) |
V8
1 2 3 4 5 | const imagesList = await storageRef.child( 'images' ).listAll(); const urls = await Promise.all( imagesList.items.map(ref => ref.getDownloadURL()) ); |
返されるURLはフルパスなので、そのまま表示に使うことができる。
1 2 3 | [ "https://firebasestorage.googleapis.com/v0/b/…=media&token=…" , "https://firebasestorage.googleapis.com/v0/b/…=media&token=…" ] |
ファイルのアップロード
まず、保存するファイルの参照を ref で作成する。
1 2 3 4 5 | // V9 import { getStorage, ref } from "firebase/storage" ; const storage = getStorage(); const imageRef = ref(storage, 'images/star.jpg' ); |
フォームから受け取ったFileまたはBlobの場合、uploadBytes に渡すだけで保存ができる。
1 | const result = await uploadBytes(imageRef, file) |
アップロードの管理
途中でキャンセルするような操作が必要な場合は、 uploadBytesResumable を利用する。
1 2 3 4 5 6 7 8 9 10 11 | // V9 const uploadTask = uploadBytesResumable(imageRef, file); // Pause the upload uploadTask.pause(); // Resume the upload uploadTask.resume(); // Cancel the upload uploadTask.cancel(); |
アップロードの進行状況を監視する
uploadBytesResumable が返す UploadTask の state_changed
にイベントハンドラを設定しておくと、アップロードの進捗を表示することができる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | // V9 const uploadTask = uploadBytesResumable(imageRef, file); uploadTask.on( 'state_changed' , (snapshot) => { // 進行状況、一時停止、再開などの状態変化イベントを観察する // アップロードされたバイト数とアップロードされる合計バイト数を含む、タスクの進行状況を取得します const progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100; console.log( 'Upload is ' + progress + '% done' ); switch (snapshot.state) { case 'paused' : console.log( 'Upload is paused' ); break ; case 'running' : console.log( 'Upload is running' ); break ; } }, (error) => { // 失敗したアップロードの処理 }, () => { // 成功したアップロードを完了時に処理する // たとえば、ダウンロード URL を取得します: https://firebasestorage.googleapis.com/... getDownloadURL(uploadTask.snapshot.ref).then((downloadURL) => { console.log( 'File available at' , downloadURL); }); } ); |
複数のファイルをアップロードする
やることは単体ファイルのアップロードと同じなので、Promise.allを使えば良い。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | // V9 const fileList = [] // Files[] const downloadURLs = await Promise.all( fileList.map((file) => { return new Promise<string>((resolve, reject) => { const storageRef = ref(storage, `images/${file.name}`); const uploadTask = uploadBytesResumable(storageRef, file); uploadTask.on( 'state_changed' , (snapshot) => { const progress = Math.round((snapshot.bytesTransferred / snapshot.totalBytes) * 100); console.log(`Upload is ${progress}% done`); // .... }, (error) => { switch (error.code) { case 'storage/unauthorized' : // User doesn't have permission to access the object console.error(`${file.name} Upload Error: unauthorized`) break ; case 'storage/canceled ': // User canceled the upload break; case ' storage/unknown ': // Unknown error occurred, inspect error.serverResponse console.error(`${file.name} Upload Error: unknown`); break; } reject(); }, () => { getDownloadURL(uploadTask.snapshot.ref).then((downloadURL) => { console.log(file.name, ' available at', downloadURL); resolve(downloadURL); }); }, ); }); }), ); |