Azure Blob StorageへPythonを使ってファイルアップロードする

# 概要
最近Azureを使った開発が増えてきているので勉強がてら公式のドキュメントを参考にしつつ、Azure Blob Storageへファイルアップロードを実装してみた。
流れとしては、以下流れで実装します。
1 Blob Storageコンテナ内のblob一覧を取得する
2 Blob Storageコンテナへファイルをアップロードする。

※会社PCではない。Azureも個人環境である。

#### 前提
前提条件は公式を参照します。以下内容を守っていればいいかと。
Azure アカウントの作成。Blob Storageの作成。コンテナの作成等は完了しています。
ちなみにAzure CLIダウンロードも必須です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/645607/161bce19-fa5f-1054-72e3-90147b9ff02f.png)

[公式リンク](URL "https://learn.microsoft.com/ja-jp/azure/storage/blobs/storage-quickstart-blobs-python?tabs=managed-identity%2Croles-azure-portal%2Csign-in-visual-studio-code&pivots=blob-storage-quickstart-scratch")

# コンテナに保存されているファイル一覧を取得する
まずは、コンテナ内のファイル一覧を取得しましょう。
以下uploadtestコンテナ内に既に保存されているtestdocument.txtの表示を実装します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/645607/191a4ace-13f3-90f6-2625-a38d5a972416.png)


```python
import os
from azure.identity import DefaultAzureCredential
from azure.storage.blob import BlobServiceClient
import logging

# ログの設定
logging.basicConfig(level=logging.DEBUG)

try:
    print("Azure Blob Storage へ接続を開始しました")

    # Azure Storage アカウントのURL
    account_url = "https://<ここにストレージアカウント名を入力>.blob.core.windows.net"
    # デフォルトの資格情報を取得
    default_credential = DefaultAzureCredential(logging_enable=True)

    # BlobServiceClientオブジェクトを作成
    blob_service_client = BlobServiceClient(account_url, credential=default_credential)

    # 既存のコンテナ名を指定
    container_name = "ここに作成済みコンテナ名を入力"  

    # 指定したコンテナのクライアントを取得
    container_client = blob_service_client.get_container_client(container_name)

    # コンテナ内のブロブをリスト
    print(f"Listing blobs in container: {container_name}")
    blob_list = container_client.list_blobs()
    for blob in blob_list:
        print("\t" + blob.name)

# 例外処理エラー結果出力
except Exception as ex:
    print('Exception:')
    print(ex)

```

#### 実行
まずVscodeのターミナル上で以下コマンドを実行しAzure 認証する
```bash
az login
```

ターミナルでpythonを起動し、testdocument.txtが表示されてればOK
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/645607/89d50d2d-3b53-8416-4898-1928823159d2.png)

#### VsCodeからAzureへの認証について
今回はDefaultAzureCredentialクラスを使って認証している。
他にもBlob Storageの接続文字列を使ってアクセスする方法がある。接続文字列を使う場合は、システム環境変数に定義し、ハードコーディングしないように気をつけましょう
[公式リンク](URL "https://learn.microsoft.com/ja-jp/java/api/com.azure.identity.defaultazurecredential?view=azure-java-stable")

# Azure Blob Storageへファイルアップロード
簡単にコードの解説をします。
１　dataフォルダを作成（既にフォルダがあれば作成しない）
２　dataフォルダ内にGUID名のファイルを作成
３　ファイルの中身に"Hello World"を記述
４　２で作成したファイルをBlob Storageのコンテナへアップロード
５　最後にBlob Storageのコンテナ内一覧を取得、ターミナルへprint

```python
import os
import uuid
from azure.identity import DefaultAzureCredential
from azure.storage.blob import BlobServiceClient, BlobClient, ContainerClient

try:
    print("Azure Blob Storage Python quickstart sample")

    # Azure Storage アカウントのURL
    account_url = "https://<ここにストレージアカウント名を入力>.blob.core.windows.net"
    # デフォルトの資格情報を取得
    default_credential = DefaultAzureCredential()

    # BlobServiceClientオブジェクトを作成
    blob_service_client = BlobServiceClient(account_url, credential=default_credential)

    # 既存のコンテナ名を指定
    container_name = "ここに作成済みコンテナ名を入力" 

    # 指定したコンテナのクライアントを取得
    container_client = blob_service_client.get_container_client(container_name)

    # Create a local directory to hold blob data
    local_path = "./data"
    os.makedirs(local_path, exist_ok=True)

    # Create a file in the local data directory to upload and download
    local_file_name = str(uuid.uuid4()) + ".txt"
    upload_file_path = os.path.join(local_path, local_file_name)

    # Write text to the file
    with open(upload_file_path, mode='w') as file:
        file.write("Hello, World!")

    # Create a blob client using a specific blob name
    specific_blob_name = local_file_name
    blob_client = blob_service_client.get_blob_client(container=container_name, blob=specific_blob_name)

    print("\nUploading to Azure Storage as blob:\n\t" + specific_blob_name)

    # Upload the created file
    with open(upload_file_path, mode="rb") as data:
        blob_client.upload_blob(data)

    print("\nBlob uploaded successfully.")

    # コンテナ内のブロブをリスト
    blob_list = container_client.list_blobs()
    for blob in blob_list:
        print("\t" + blob.name)

#例外処理エラー結果出力
except Exception as ex:
    print('Exception:')
    print(ex)
```

#### 実行
単純に実行すると以下エラーが出ます。アクセス権ないぜって怒られてますね。
Blob Storageへの書き込み権限を付与しましょう。適切なアクセス件付与をAzure Portalから実施します。
```bash
Azure Blob Storage Python quickstart sample

Uploading to Azure Storage as blob:
        my-specific-blob-name.txt
Exception:
This request is not authorized to perform this operation using this permission.
RequestId:8b7dd75b-a01e-001f-0fdc-e4f089000000
Time:2024-08-02T13:03:30.2727038Z
ErrorCode:AuthorizationPermissionMismatch
Content: <?xml version="1.0" encoding="utf-8"?><Error><Code>AuthorizationPermissionMismatch</Code><Message>This request is not authorized to perform this operation using this permission.
RequestId:8b7dd75b-a01e-001f-0fdc-e4f089000000
Time:2024-08-02T13:03:30.2727038Z</Message></Error>
```

アクセス権付与して再度実行すると
Hello Worldと記述されたファイルがアップロードされてますねOKです
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/645607/059b87de-ebbf-90ed-5238-615c9b16eaec.png)

また、Vscodeターミナル上でも以下画像のようにアップロード成功と、Blob Storageコンテナ内一覧が表示されます。
（画像追加忘れていたのでコンテナ内の画像に多少差異がある点は無視してください）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/645607/1c424316-9b12-800f-c0d2-df8ed72b0905.png)