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

【手順3】画像のパスを”gs://〜”形式から”https://〜”形式に変換する

●Point
・手順1で利用したサービスアカウントキーのJSONファイルは、この処理でも利用する。
・下記のコードでは、画像を署名つきURLに変更する。この署名付きURLの画像を参照できるのは7日間のみ。
 これ以上の期間もしくは無期限にする場合はFirebaseのルールを指定して認証なしでアクセス可とする方法も
 あるが、セキュリティリスクもあるので注意が必要。

●gs形式からhttps形式への変換プログラム(結果はfirebaseコンソールにて確認)

import firebase_admin
from firebase_admin import credentials, firestore, storage
from datetime import timedelta
import json

# ##################################################################
#  FIreStore Storage  gs:// ==> http:// 変換
# ##################################################################

# Firebase Admin SDKの初期化
cred = credentials.Certificate('test-app-firebase.json')
firebase_admin.initialize_app(cred, {
    'storageBucket':  "test-app.appspot.com"
})

db = firestore.client()
bucket = storage.bucket()

def convert_gs_to_https(gs_url):
    try:
        # gs:// URLをFirebase Storage Referenceに変換
        storage_ref = bucket.blob(gs_url.replace('gs://test-app.appspot.com/', ''))
        # https:// URLを取得
        download_url = storage_ref.generate_signed_url(
            version="v4",
            expiration=timedelta(days=7)  ### 有効期限は最大7日
        )
        return download_url
    except Exception as e:
        print(f"Error converting URL {gs_url}: {e}")
        return None

def update_photos_field(collection_name):
    docs = db.collection(collection_name).stream()

    for doc in docs:
        data = doc.to_dict()
        print(data)
        if 'photos' in data and isinstance(data['photos'], str):  # photosが文字列型であることを確認
            gs_url = data['photos']
            if gs_url.startswith('gs://'):
                https_url = convert_gs_to_https(gs_url)
                if https_url:
                    # Firestoreドキュメントを更新
                    db.collection(collection_name).document(doc.id).update({'photos': https_url})
                    print(f"Updated document {doc.id} with new URL")
                else:
                    print(f"Failed to convert URL for document {doc.id}")
            else:
                print(f"Document {doc.id} already has an https URL")
        else:
            print(f"No photos field or not a string in document {doc.id}")


def main():
    collection_name = 'samplePersons'  # コレクション名を指定
    update_photos_field(collection_name)

if __name__ == '__main__':
    main()
  


●認証なしの場合のルール指定

service firebase.storage {
  match /b/{bucket}/o {
    match /{allPaths=**} {
      allow read: if true; // 認証なしで読み取りを許可
      allow write: if false; // 書き込みを禁止(必要に応じて設定を変更)
    }
  }
}