Firestoreに画像を含んだデータを格納する方法(1/3)

Firestoreに画像を含んだデータを格納する方法について3回に分割してメモする。
Flutterからのデータ格納の機能は外したので、Pythonで一括登録することとした。
Pythonの勉強がようやく活きてきた。

●前提
・画像はFirestoreには格納できないので、Storageに格納。
・Firestoreには、Storageのパスをフィールドに定義する。
 ただし、このパスは、”gs://〜”の形式なので、”https://〜”の形式に変換する必要がある。
・Pycharmを利用。画像データや、JSONファイルはプロジェクト直下に配置する。

●手順
1.画像をStorageに格納する。
2.画像のパスを含んだデータをJSON形式で作成し、Firestoreに一括登録する。
3.Firestoreに登録した画像のパスを”gs://〜”形式から”https://〜”形式に変換する

【手順1】画像をStorageに格納する。

●Point
・FirebaseのサービスアカウントキーのJSONファイルはfirebaseコンソールの設定画面から取得する。
・Bucketの指定は”xxx.appspot.com”。サブフォルダがある場合は、下記コードの様に連結する。
・画像データは1日キャッシュするようにキャッシュ制御ヘッダーを設定。

●サービスアカウントキーのJSONファイル(こんなファイル)

{
  "type": "service_account",
  "project_id": "test-app",
  "private_key_id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "private_key": "-----BEGIN PRIVATE KEY-----\
  (省略)
 =\n-----END PRIVATE KEY-----\n",
  "client_email": "firebase-adminsdk-xxxxx@test-app.iam.gserviceaccount.com",
  "client_id": "000000000000000000000",
  "auth_uri": "https://accounts.google.com/o/oauth2/auth",
  "token_uri": "https://oauth2.googleapis.com/token",
  "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
  "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/xxxx/firebase-adminsdk-xxxxx%55test-app.iam.gserviceaccount.com",
  "universe_domain": "googleapis.com"
}

●画像格納の実行プログラム(結果はfirebaseコンソールにて確認)

import os
import firebase_admin
from firebase_admin import credentials, firestore, storage
# ##################################################################
#  FIreStore Storage Image Upload
# ##################################################################

# FirebaseのサービスアカウントキーのJSONファイルのパス
cred = credentials.Certificate('test-app-firebase.json')
firebase_admin.initialize_app(cred, {
    'storageBucket':  "test-app.appspot.com"
})

# Storageバケットの取得
bucket = storage.bucket()
# アップロードするディレクトリのパス
local_directory = 'sample'
# サブフォルダーの指定
subfolder = 'sample'

# Firebase Storageに画像ファイルをアップロードする関数
def upload_images_to_storage(directory, subfolder):
    try:
        for filename in os.listdir(directory):
            if filename.endswith(('.png', '.jpg', '.jpeg', '.gif')):
                local_path = os.path.join(directory, filename)
                blob = bucket.blob(f'{subfolder}/{filename}')
                blob.upload_from_filename(local_path)
                    # キャッシュ制御ヘッダーの設定 1日 (3600秒x24時間=86400) キャッシュを有効にする
                blob.cache_control = 'public, max-age=86400'  
                blob.patch()  # メタデータを保存する                
                print(f'Successfully uploaded {filename} to {subfolder} in Firebase Storage.')
    except NotFound as e:
        print(f'Error: {e}')
        print('The specified bucket was not found. Please check the bucket name and your Firebase project settings.')

# 画像ファイルをアップロード
if __name__ == '__main__':
    upload_images_to_storage(local_directory, subfolder)