見出し画像

BackblazeのB2 Cloud StrageをPythonで動作させてみる

Neetになって自作のWebアプリを開発している博士です。
Webアプリを開発してきて、ユーザー情報や短いテキスト情報などを格納するのに、SQL DBを活用すれば良いことを開発していて理解しました。しかし画像が動画、PDF等の容量の比較的大きいデータについては、SQLに登録することはおすすめされません。
なぜなら、容量の大きなデータを格納してしまうと、
SQL容量の圧迫(SQLサービスのランニングコストは高い!)
データベースの検索速度やレスポンスの悪化
を招くため、容量が大きいデータについてはオブジェクトストレージに格納する必要があるようです。

本ページはBlackblazeを利用してデータを格納しダウンロードURL発行までの手順メモになります。

Backblazeって?

ackblazeは、個人向けおよびビジネス向けのクラウドストレージおよびデータバックアップサービスです。
魅力は、運用コストが既存サービスに比べ安いことで、AWSやAzureと比較しても、データ量あたりのコストが圧倒的に安価です。

主なサービス

  • 個人向けオンラインバックアップ: PCやMacから自動的にデータをバックアップし、安全にクラウドに保存します。復元はファイルのダウンロードやUSBドライブによる郵送で行えます。

  • ビジネス向けバックアップ: エンドポイント保護とサーバデータのバックアップを提供し、企業のデータ保護をサポートします。

  • B2 Cloud Storage: 高性能で低コストなクラウドストレージソリューションを提供し、データの保管、共有、管理を簡単にします。Webサイトのホスティングやアーカイブ、アプリケーションデータの保管に最適です。

今回は上記サービスの中のB2 Cloud Storageを使っていきます。

1.Bucketの作成

アカウント登録後、新しいBucketを作成します。

今回は、以下の設定でBucketを作成しました。

1A.Bucketとは、

クラウドストレージサービスにおいてデータを格納するためのコンテナのことを指します。
バケットの特徴と用途

  • 階層構造: バケットは最上位のデータ格納コンテナであり、ファイルやフォルダの階層構造を作成する基盤となります。ただし、オブジェクトストレージではフォルダは論理的な概念であり、実際にはパス名をファイル名の一部として使用して階層を模倣します。

  • 一意の名前: 各バケットはサービス全体で一意の名前を持つ必要があります。これは、インターネット上でバケットにアクセスするためのURLが他と重複しないようにするためです。

  • アクセス制御: バケットごとにアクセス権限を設定できます。公開アクセスを許可するか、特定のユーザーやグループのみにアクセスを制限することが可能です。

  • データ管理: バケットは大量のデータを格納することができ、ファイルのアップロード、ダウンロード、削除などの操作を行うことができます。また、データのライフサイクル管理を通じて古いファイルを自動的に削除する設定も可能です。

バケットの使用例

  • ウェブサイトのホスティング: 静的ファイル(HTML、CSS、JavaScript、画像ファイルなど)をバケットに保存し、公開ウェブサイトとして機能させることができます。

  • バックアップとアーカイブ: 重要なデータのバックアップを取るためにバケットを使用し、安全な場所にデータを保管します。また、長期間アクセスする必要がないデータをアーカイブする用途にも使われます。

  • コンテンツ配信: メディアファイルや大量のデータをバケットに保存し、世界中のユーザーに高速で配信するためのコンテンツ配信ネットワーク(CDN)と統合することができます。

2.アプリケーションキーの作成

アカウントアプリケーションキーを選択し、NewApplication keyを作成します。マスターキー(マスターアクセスキー)も作成可能ですが、セキュリティ的な観点から今回は、Application Keysを作成しアクセス制限します。

Application Key作成画面各項目について説明します。

Name of Key (keyName)

  • 説明: 生成するアプリケーションキーの名前です。この名前は管理目的で使用され、キーを識別するために役立ちます。

  • 用途: キーの用途や関連するプロジェクト名など、分かりやすい識別名を付けると管理が容易になります。

Allow access to Bucket(s) (bucketName)

  • 説明: このキーでアクセスを許可するバケットの名前を指定します。特定のバケット名を指定することで、そのバケットに対するアクセスのみを許可します。

  • 用途: 特定のバケットへのアクセス制限を設けたい場合に使用します。

Type of Access (capabilities)

  • 説明: キーに与えるアクセス権の種類です。Read and Write、Read Only、Write Onlyから選択できます。

  • 用途: キーを使用する目的に合わせて、必要な権限を設定します。例えば、データのバックアップのみを目的とする場合はWrite Onlyを選択します。

Allow List All Bucket Names (optional)

  • 説明: このオプションを有効にすると、キーを使用して全てのバケット名とその作成日をリスト表示できます。S3互換のList Buckets APIを使用する場合に必要です。

  • 用途: バケットの一覧が必要な場合、またはS3互換APIを利用する場合に有効にします。

File name prefix (namePrefix)

  • 説明: このプレフィックスで始まるファイル名に対してのみアクセスを許可します。指定しない場合は、設定されたバケット内の全てのファイルに対するアクセスが可能です。

  • 用途: 特定のプレフィックス(例えばプロジェクト名やユーザーIDなど)を持つファイルへのアクセスを制限したい場合に使用します。

Duration (seconds) (validDurationSeconds)

  • 説明: キーの有効期間を秒単位で指定します。指定可能な最大値は1000日未満です。指定しない場合は、キーに有効期限が設定されません。

  • 用途: 一時的なアクセス権限を与える場合や、セキュリティを高めるためにキーの使用期間を制限したい場合に使用します。

キーを作成したらキー情報をメモしておきます。

3.必要パッケージのインストール

pip install b2sdk

4.APIでB2に接続しバケット一覧を取得してみる

下記コードの場合、key設定でアクセス可能なバケットを絞っている場合はエラーが発生します。

from b2sdk.v2 import InMemoryAccountInfo, B2Api

# Backblaze B2のアプリケーションキーIDとアプリケーションキーを設定
application_key_id = 'yourApplicationKeyId'  # 実際のキーIDに置き換えてください
application_key = 'yourApplicationKey'  # 実際のアプリケーションキーに置き換えてください

# B2 APIクライアントの初期化
account_info = InMemoryAccountInfo()
b2_api = B2Api(account_info)
b2_api.authorize_account("production", application_key_id, application_key)

# アカウントに関連するバケットの一覧を取得
buckets = b2_api.list_buckets()

# バケットの情報を表示
print("バケット一覧:")
for bucket in buckets:
    print(f"バケット名: {bucket.name}, バケットID: {bucket.id}")

5.APIで画像をアップロードしてみる

適当な画像をB2にアップロードします。今回は、AITuberみらいの過去絵をアップロードしてみました。

みらい立ち絵

画像をpyと同一ディレクトリーに保存し、以下のコードで画像をアップロードします。

5A.APIを用いてアップロードしてみる

from b2sdk.v2 import InMemoryAccountInfo, B2Api

# Backblaze B2のアプリケーションキーIDとアプリケーションキーを設定
application_key_id = 'yourApplicationKeyId'  # 実際のキーIDに置き換えてください
application_key = 'yourApplicationKey'  # 実際のアプリケーションキーに置き換えてください

# B2APIクライアントを初期化
info = InMemoryAccountInfo()
b2_api = B2Api(info)
b2_api.authorize_account('production', application_key_id, application_key)

# アップロードするPDFファイルのパス
pdf_file_path = 'good2.png'

# B2バケット名
bucket_name = 'test-bucket-gorilla'

# PDFファイルをアップロード
bucket = b2_api.get_bucket_by_name(bucket_name)
file_info = {'content_type': 'image/png',
             'original_filename':'good2.png'}

file_name = 'image1.png'

with open(pdf_file_path, 'rb') as file:
    file_data = file.read()
    uploaded_file = bucket.upload_bytes(file_data, file_name, file_info=file_info)

上記コードでは、good2.pngをimage1.pngという名前でアップロードし、更に、

{'content_type': 'image/png',
'original_filename':'good2.png'}

というファイルinfoデータを付加しています。

メモ「bucket.upload_bytesメソッドパラメータ一覧」

パラメータ
data_bytes (bytes):
アップロードするデータのバイト列です。
file_name (str): B2内でのファイル名です。ファイルの拡張子は、デフォルトのMIMEタイプの決定に使用されます。
content_type (str, None): アップロードするファイルのMIMEタイプです。Noneを指定すると、ファイル名の拡張子に基づいてデフォルトのMIMEタイプが選択されます。
file_info (dict, None): ファイルに関連付ける追加のメタデータです。キーと値のペアの辞書で指定します。Noneを指定すると、追加のメタデータは保存されません。
progress_listener (b2sdk.v2.AbstractProgressListener, None): アップロードの進捗を追跡するためのリスナーオブジェクトです。Noneを指定すると、進捗は追跡されません。
encryption (b2sdk.v2.EncryptionSetting): アップロードするファイルの暗号化設定です。デフォルトではNoneが指定されています。
file_retention (b2sdk.v2.FileRetentionSetting): ファイルの保持設定です。法的保持やその他の保持ポリシーを設定できます。
legal_hold (bool): 法的ホールドの設定です。ファイルを不変の状態に保つ必要がある場合に使用します。
large_file_sha1 (Sha1HexDigest, None): アップロードされるファイルのSHA-1ハッシュです。主に大きなファイルのアップロードで使用されます。Noneの場合は、ハッシュは未知です。
custom_upload_timestamp (int, None): オブジェクトの作成日を上書きするためのタイムスタンプです。エポックからのミリ秒単位で指定します。
cache_control, expires, content_disposition, content_encoding, content_language: これらはHTTPヘッダーに関連するオプショナルな設定です。キャッシュの制御、コンテンツの有効期限、コンテンツの処理方法、エンコーディング、使用言語を指定するために使用されます。それぞれRFC 2616に基づいた構文で指定します。

返り値
rtype: b2sdk.v2.FileVersion:
アップロード操作の結果として、b2sdk.v2.FileVersion オブジェクトが返されます。このオブジェクトには、アップロードされたファイルのバージョン情報が含まれています。

5B.アップロードされた画像を確認する

コード実行後、アップロード状況をBackblaze側で確認してみましょう。

Browse Filesより、該当のDBを選択し、image1.pngを選択します。

Detailsを表示すると画像名や、URLの他、設定したFile Infoが適応されていることがわかります。

メモ 「Fguidと、sha1はなにか?」:

fileId (Fguid)
定義:
Backblaze B2では、アップロードされた各ファイルには一意の識別子が割り当てられます。この識別子はfileIdと呼ばれ、外部からファイルを指し示す際に使用されます。例えば、アップロードしたファイルをダウンロードするためのリンクを生成する際や、ファイルに関する情報を問い合わせる際にfileIdが必要となります。
用途: fileIdは、Backblaze B2内のファイルを一意に識別するために使用される重要なキーです。バケット内でファイルを操作するAPIコールを行う際に、このIDを指定して特定のファイルを参照します。

sha1定義: sha1は、ファイルの内容から計算されるハッシュ値です。SHA-1(Secure Hash Algorithm 1)は、任意の長さのデータから160ビット(20バイト)のハッシュ値を生成する暗号学的ハッシュ関数です。ファイルがアップロードされる際に、その内容からsha1ハッシュ値が計算され、Backblaze B2によって記録されます。
用途: sha1ハッシュ値は、ファイルの完整性(データが変更されていないこと)を検証するために使用されます。ダウンロード時にクライアント側で同じハッシュ値を計算し、アップロード時に計算された値と比較することで、ファイルが転送中に改ざんされていないかを確認できます。また、異なるファイルが偶然にも同じsha1値を持つことは極めて稀であるため、ファイルの一意性の確認にも役立ちます。

6.lsメソッドを利用してAPIでアップロードされたファイルをリストで取得する

lsメソッドを利用してファイルリストを取得する例

from b2sdk.v2 import InMemoryAccountInfo, B2Api

# 認証情報
application_key_id = 'yourApplicationKeyId'
application_key = 'yourApplicationKey'
bucket_name = 'yourBucketName'

# B2 APIクライアントの初期化
info = InMemoryAccountInfo()
b2_api = B2Api(info)
b2_api.authorize_account("production", application_key_id, application_key)

# バケットの取得
bucket = b2_api.get_bucket_by_name(bucket_name)

# リストするフォルダの指定(空文字列でトップレベルフォルダ)
folder_to_list = ''

# ファイルリストを取得(ここでは再帰的にリストしない例)
for file_version, folder_name in bucket.ls(folder_to_list=folder_to_list, recursive=False):
    print(f'ファイル名: {file_version.file_name}, フォルダ名: {folder_name}')

アップロードされたファイル情報は、.lsメソッドを使用して取得します。

このメソッドは、Backblaze B2のバケット内のファイルと"フォルダ"の一覧を生成するために使われます。
Backblaze B2は、基本的にはファイルのフラットな名前空間を持っていますが、/をデリミタとして使用することにより、フォルダ構造を模倣します。
.lsメソッドはこの慣習を利用して、特定の"フォルダ"内のファイルとサブフォルダをリストする機能を提供します。

.lsメソッドは、いくつかのパラメータを受け取ることができます。
たとえば、folder_to_listパラメータを使用して、特定のフォルダ内のファイルのみをリストすることができます。
また、recursiveフラグをTrueに設定することで、指定したフォルダおよびそのすべてのサブフォルダ内のファイルを再帰的にリストすることができます。

latest_onlyパラメータを使用して、ファイルの最新バージョンのみを取得するか、すべてのバージョンの情報を取得するかを選択することができます。fetch_countパラメータによって、一度に取得するファイルの数を制限することも可能です。これにより、大量のファイルが存在するバケットを扱う際のパフォーマンスと効率が向上します。

.lsメソッドの戻り値は、ファイルバージョンオブジェクトとフォルダ名のタプルのジェネレータです。このジェネレータをイテレートすることで、バケット内のファイルとフォルダの情報を順に取得することができます。この機能は、ファイルの整理、検索、管理タスクを自動化するスクリプトやアプリケーションを開発する際に特に便利です。

.lsメソッドのパラメータ

  • folder_to_list (str = ''):

    • リストするフォルダの名前を指定します。先頭に"/"を含めることはできません。

    • 空文字列を指定した場合は、トップレベルのフォルダ(バケットのルート)が対象となります。

  • latest_only (bool = True):

    • Falseを指定すると、ファイルのすべてのバージョンに関する情報が返されます。

    • Trueを指定すると、最新バージョンのファイル情報のみが返されます。

  • recursive (bool = False):

    • Trueを指定すると、指定されたフォルダ及びその全てのサブフォルダ内のファイルがリストされます。

    • Falseの場合は、指定されたフォルダの直下にあるファイルのみがリストされます。

  • fetch_count (int | None = LIST_FILE_NAMES_MAX_LIMIT):

    • APIコールあたりにリストするエントリ数を指定します。1から10000までの値を指定できます。

    • Noneを指定した場合、デフォルトの最大リミットが使用されます。

  • with_wildcard (bool = False):

    • Trueを指定すると、folder_to_listでワイルドカード("*", "?", "[]", "[!]")を使用できます。このモードでは、folder_to_listはファイル名やパターンとして扱われます。

    • ワイルドカードを使用するには、recursive=Trueと一緒に設定する必要があります。

  • filters (Sequence[Filter] = ()):

    • サーバーから返されたファイルに適用するフィルターのリストを指定します。これにより、特定の条件を満たすファイルのみをリストすることができます。

返り値

  • rtype: generator[tuple[b2sdk.v2.FileVersion, str]]

  • returns: (file_version, folder_name)タプルのジェネレータです。これにより、ファイルバージョンオブジェクトとそのファイルが存在するフォルダ名を順に取得できます。

7.ファイルを検索して、ファイルのダウンロードURLを取得する

from b2sdk.v2 import InMemoryAccountInfo, B2Api

# Backblaze B2の認証情報
application_key_id = 'yourApplicationKeyId'  # あなたのアプリケーションキーIDに置き換えてください
application_key = 'yourApplicationKey'  # あなたのアプリケーションキーに置き換えてください
bucket_name = 'yourBucketName'  # 操作を行いたいバケットの名前に置き換えてください
file_name = 'yourFileName'  # 検索したいファイル名に置き換えてください

# B2 APIクライアントの初期化
info = InMemoryAccountInfo()
b2_api = B2Api(info)
b2_api.authorize_account("production", application_key_id, application_key)

# バケットの取得
bucket = b2_api.get_bucket_by_name(bucket_name)

# URLの表示
print(bucket.get_download_url(filename=file_name))

このコードは、Backblaze B2 Cloud Storage上にある特定のファイルのダウンロードURLを生成し、表示するためのPythonスクリプトです。

bucket.get_download_url(filename=file_name)を使用して、指定されたファイル名のダウンロードURLを取得し、表示します。

8.画像をアップロードし、ダウンロードURLを取得する

from b2sdk.v2 import InMemoryAccountInfo, B2Api

# Backblaze B2の認証情報
application_key_id = 'yourApplicationKeyId'  # あなたのアプリケーションキーIDに置き換えてください
application_key = 'yourApplicationKey'  # あなたのアプリケーションキーに置き換えてください
bucket_name = 'yourBucketName'  # 操作を行いたいバケットの名前に置き換えてください
file_name = 'yourFileName'  # ファイル名に置き換えてください

# B2 APIクライアントの初期化
info = InMemoryAccountInfo()
b2_api = B2Api(info)
b2_api.authorize_account("production", application_key_id, application_key)

# バケットの取得
bucket = b2_api.get_bucket_by_name(bucket_name)

# アップロードする画像ファイルのパス
image_file_path = 'good2.png'  # アップロードしたい画像ファイルのパスに置き換えてください
file_name = 'image.png'  # B2に保存されるファイル名

# 画像ファイルをアップロード
with open(image_file_path, 'rb') as file:
    file_data = file.read()
    uploaded_file = bucket.upload_bytes(file_data, file_name, content_type='image/png')

# ダウンロードURLを取得
download_url = b2_api.get_download_url_for_fileid(uploaded_file.id_)

# ダウンロードURLを表示
print(f"ダウンロードURL: {download_url}")

上記コードはアップロード情報よりダウンロードURLを取得し返します。
またUpload_fileには、以下の情報は含まれています。

FileVersion('4_z7a21ca2383885e5e83eb0a18_f116399a26_1018_t0047_0861496968', <b2sdk.v2.api.B2Api object at 0x00000201F5384790>, 'image.png', 637606, 'image/png', 'aa4e517...f0e45', True, {}, 1710861496968, <EncryptionSetting(EncryptionMode.NONE, None, None)>, <LegalHold.UNKNOWN: 'unknown'>, FileRetentionSetting('unknown', None), 1710861496968, None, 'a1a33ba8', '7a21ca238e83eb0a18', 'e8625529bf9de7f654e7e40', 'upload', None)

最初の長い文字列: これはファイルのID(fileId)です。ファイルを一意に識別するためにBackblaze B2によって割り当てられます。
<b2sdk.v2.api.B2Api object>: これはB2Apiオブジェクトのインスタンスを示し、API呼び出しを行うために使用されるオブジェクトです。
'image.png': アップロードされたファイルの名前です。
637606: ファイルのサイズ(バイト単位)です。
'image/png': ファイルのMIMEタイプです。
'aa4e517...f0e45': ファイルのSHA1ハッシュ値です。ファイルの完整性を確認するために使用されます。
True: これは、ファイルがアクション(たとえば、アップロード)の結果として生成されたものかどうかを示します。
{}: これはファイルに関連付けられたカスタムメタデータを表します。空の辞書はメタデータがないことを意味します。
1710861496968: ファイルのアップロードタイムスタンプ(エポックからのミリ秒)です。
<EncryptionSetting(EncryptionMode.NONE, None, None)>: ファイルの暗号化設定を示します。この場合、暗号化は行われていません。
<LegalHold.UNKNOWN: 'unknown'>: 法的ホールドの状態を示します。この場合、状態は不明です。
FileRetentionSetting('unknown', None): ファイルの保持設定を示します。この場合、設定は不明です。
更に他の数値や識別子: これらは内部的な管理や、ファイルがアップロードされた環境に関連する追加の情報です。


この記事が気に入ったらサポートをしてみませんか?