F# を使用して Azure Blob Storage を始める

Azure Blob Storage は、非構造化データをオブジェクトまたは BLOB としてクラウドに格納するサービスです。 Blob Storage は、ドキュメント、メディア ファイル、アプリケーション インストーラーなど、任意の種類のテキスト データやバイナリ データを格納できます。 Blob Storage は、オブジェクト ストレージとも呼ばれます。

この記事では、BLOB ストレージを使用して一般的なタスクを実行する方法について説明します。 サンプルは、 Azure.Storage.Blobs パッケージと共に F# を使用して記述されています。 紹介するタスクでは、BLOB のアップロード、一覧表示、ダウンロード、削除の方法を扱います。

BLOB ストレージの概念の概要については、BLOB ストレージの .NET ガイドをご覧ください。 これらのチュートリアルでは、簡単にするために接続文字列を使用して Azure で認証しています。 運用アプリケーションの場合は、セキュリティを強化するために、 マネージド ID または Azure.Identity ライブラリ で Microsoft Entra ID を使用する必要があります。

Important

この記事では、モダン Azure.Storage.Blobs パッケージを使用します。 非推奨の WindowsAzure.Storage または Microsoft.Azure.Storage.Blob パッケージを使用していた古いコードから更新する場合は、パッケージ参照と名前空間宣言を更新する必要があります。 移行ガイダンスについては、「 Azure.Storage.BLOB への移行」を参照してください。

F# 開発者は、Azure Blob Storage を操作するためのより慣用的な F# API を提供する FSharp.Azure.Blob ライブラリを検討できます。 このコミュニティ ライブラリには、F# での BLOB 操作をより自然なものにする慣用的な F# 関数とパターンが用意されています。

前提条件

このガイドを使用するには、まず Azure ストレージ アカウントを作成する必要があります。 また、このアカウントのストレージ アクセス キーも必要です。

F# スクリプトを作成して F# インタラクティブを開始する

この記事のサンプルは、F# アプリケーションと F# スクリプトのどちらでも使用できます。 F# スクリプトを作成するには、.fsx 拡張子のファイルを作成します。たとえば、F# 開発環境では blobs.fsx です。

スクリプトを実行する方法

F# インタラクティブ (dotnet fsi) は、対話形式で起動することも、コマンド ラインから起動してスクリプトを実行することもできます。 コマンド ラインの構文は次のとおりです

> dotnet fsi [options] [ script-file [arguments] ]

スクリプトにパッケージを追加する

#r nuget:package nameを使用してAzure.Storage.Blobs パッケージをインストールし、必要な名前空間をopenします。

> #r "nuget: Azure.Storage.Blobs"
open Azure.Storage.Blobs
open Azure.Storage.Blobs.Models
open Azure.Storage.Blobs.Specialized

名前空間宣言の追加

次の open ステートメントを blobs.fsx ファイルの先頭に追加します。

open System
open System.IO
open Azure.Storage.Blobs // Namespace for Blob storage types
open Azure.Storage.Blobs.Models
open Azure.Storage.Blobs.Specialized
open System.Text

接続文字列を取得する

このチュートリアルでは、Azure Storage 接続文字列が必要です。 接続文字列の詳細については、ストレージ接続文字列の構成に関する記事をご覧ください。

このチュートリアルでは、次のようにスクリプトに接続文字列を入力します。

let storageConnString = "..." // fill this in from your storage account

ローカル ダミー データを作成する

開始する前に、スクリプトのディレクトリにダミーのローカル データを作成します。 後でこのデータをアップロードします。

// Create a dummy file to upload
let localFile = "./myfile.txt"
File.WriteAllText(localFile, "some data")

BLOB サービス クライアントを作成する

BlobContainerClient 型を使用すると、コンテナーを作成し、BLOB ストレージ内に格納されている BLOB を取得することができます。 コンテナー クライアントを作成する方法の 1 つを次に示します。

let container = BlobContainerClient(storageConnString, "mycontainer")

これで、Blob Storage に対してデータの読み取りと書き込みを実行するコードを記述する準備が整いました。

コンテナーを作成する

この例は、コンテナーがない場合に、コンテナーを作成する方法を示しています。

container.CreateIfNotExists()

既定では、新しいコンテナーはプライベートなので、このコンテナーから BLOB をダウンロードするにはストレージ アクセス キーを指定する必要があります。 コンテナー内のファイルをだれでも利用できるようにする場合は、次のコードを使ってコンテナーをパブリックに設定できます。

let permissions = PublicAccessType.Blob
container.SetAccessPolicy(permissions)

パブリック コンテナー内の BLOB は、インターネットに接続しているすべてのユーザーが表示できますが、変更または削除できるのは、適切なアカウント アクセス キーまたは Shared Access Signature を持っているユーザーだけです。

コンテナーに BLOB をアップロードする

Azure Blob Storage では、ブロック BLOB とページ BLOB がサポートされています。 通常、ブロック BLOB 型を使用することが推奨されます。

ファイルをブロック BLOB にアップロードするには、コンテナー クライアントを取得し、それを使用してブロック BLOB の参照を取得します。 BLOB の参照を取得したら、Upload メソッドを呼び出すことによって、データの任意のストリームを BLOB にアップロードできます。 この操作により、Blob の内容が上書きされ、ブロック BLOB が存在しない場合は新しく作成されます。

// Retrieve reference to a blob named "myblob.txt".
let blockBlob = container.GetBlobClient("myblob.txt")

// Create or overwrite the "myblob.txt" blob with contents from the local file.
use fileStream = new FileStream(localFile, FileMode.Open, FileAccess.Read, FileShare.Read)
do blockBlob.Upload(fileStream)

コンテナー内の BLOB を一覧表示する

コンテナー内の BLOB を一覧表示するには、まず、コンテナーの参照を取得します。 次に、コンテナーの GetBlobsByHierarchy メソッドを使用して、その中の BLOB やディレクトリを取得できます。 このメソッドは、BLOB のプロパティとメタデータへのアクセスを提供する BlobItem オブジェクトを返します。

for item in container.GetBlobsByHierarchy() do
    printfn $"Blob name: {item.Blob.Name}"

たとえば、 photosという名前のコンテナーに次の一連のブロック BLOB があったとします。

photo1.jpg
2015/architecture/description.txt
2015/architecture/photo3.jpg
2015/architecture/photo4.jpg
2016/architecture/photo5.jpg
2016/architecture/photo6.jpg
2016/architecture/description.txt
2016/photo7.jpg\

1 つのコンテナーに対して GetBlobsByHierarchy を呼び出すと (上記サンプルを参照)、階層化された一覧が返されます。

Directory: https://<accountname>.blob.core.windows.net/photos/2015/
Directory: https://<accountname>.blob.core.windows.net/photos/2016/
Block blob of length 505623: https://<accountname>.blob.core.windows.net/photos/photo1.jpg

BLOB をダウンロードする

BLOB をダウンロードするには、まず BLOB の参照を取得し、次に DownloadTo メソッドを呼び出します。 次の例は、DownloadTo メソッドを使用して、ローカル ファイルに保存できるストリーム オブジェクトに BLOB の内容を転送します。

// Retrieve reference to a blob named "myblob.txt".
let blobToDownload = container.GetBlobClient("myblob.txt")

// Save blob contents to a file.
do
    use fileStream = File.OpenWrite("path/download.txt")
    blobToDownload.DownloadTo(fileStream)

DownloadContent メソッドを使用して BLOB の内容をテキスト文字列としてダウンロードすることもできます。

let text = blobToDownload.DownloadContent().Value.Content.ToString()

BLOB を削除する

BLOB を削除するには、まず BLOB の参照を取得し、次にその Delete メソッドを呼び出します。

// Retrieve reference to a blob named "myblob.txt".
let blobToDelete = container.GetBlobClient("myblob.txt")

// Delete the blob.
blobToDelete.Delete()

BLOB をページで非同期に一覧表示する

多数の BLOB を一覧表示する場合や、1 回の一覧表示操作で返される結果の数を制御する場合には、BLOB の一覧を結果のページで表示できます。 この例では、ページで結果を返す方法を示します。

この例では、GetBlobsByHierarchyBlobContainerClient メソッドを使用した階層リストを示します。

let ListBlobsSegmentedInHierarchicalListing(container:BlobContainerClient) =
        // List blobs to the console window, with paging.
        printfn "List blobs in pages:"

        // Call GetBlobsByHierarchy to return an async collection 
        // of blobs in this container. AsPages() method enumerate the values 
        //a Page<T> at a time. This may make multiple service requests.

        for page in container.GetBlobsByHierarchy().AsPages() do
            for blobHierarchyItem in page.Values do 
                printf $"The BlobItem is : {blobHierarchyItem.Blob.Name} "

        printfn ""

これでこの階層リスト ルーチンを次のように使用できます。 まず、ダミー データをアップロードします (このチュートリアルで既に作成したローカル ファイルを使用します)。

for i in 1 .. 100 do
    let blob = container.GetBlobClient($"myblob{i}.txt")
    blob.Upload(localFile)

ここで、ルーチンを呼び出します。


追加 BLOB への書き込み

追加 BLOB は、ログ記録などの追加操作のために最適化されています。 ブロック BLOB のように、追加 BLOB はブロックで構成されますが、追加 BLOB に新しいブロックを追加する場合は常に BLOB の最後に追加されます。 追加 BLOB の既存のブロックは更新したり、削除することはできません。 追加 BLOB のブロック ID は、ブロック BLOB のようには公開されません。

追加 BLOB 内の各ブロックは、最大 4 MB のサイズにすることができます。また追加 BLOB には最大 50,000 のブロックを含めることができます。 よって追加 BLOB の最大サイズは 195 GB (4 MB X 50,000 ブロック) よりも少し大きくなります。

次の例では、新しい追加 BLOB を作成し、データを追加してシンプルなログ記録操作をシミュレートしています。

let appendContainer = BlobContainerClient(storageConnString, "my-append-blobs")

// Create the container if it does not already exist.
appendContainer.CreateIfNotExists() |> ignore

// Get a reference to an append blob.
let appendBlob = appendContainer.GetAppendBlobClient("append-blob.log")

// Create the append blob. Note that if the blob already exists, the 
// CreateIfNotExists() method will overwrite it. You can check whether the 
// blob exists to avoid overwriting it by using appendBlob.Exists().
appendBlob.CreateIfNotExists()

let numBlocks = 10

// Generate an array of random bytes.
let rnd = Random()
let bytesArray = Array.zeroCreate<byte>(numBlocks)
rnd.NextBytes(bytesArray)

// Simulate a logging operation by writing text data and byte data to the 
// end of the append blob.
for i in 0 .. numBlocks - 1 do
    let msg = sprintf $"Timestamp: {DateTime.UtcNow} \tLog Entry: {bytesArray.[i]}\n"
    let array = Encoding.ASCII.GetBytes(msg);
    use stream = new MemoryStream(array)
    appendBlob.AppendBlock(stream)

// Read the append blob to the console window.
let downloadedText = appendBlob.DownloadContent().Value.Content.ToString()
printfn $"{downloadedText}"

3 つの BLOB タイプにおける違いの詳細については、「 Understanding Block Blobs, Page Blobs, and Append Blobs (ブロック BLOB、ページ BLOB、追加 BLOB を理解する) 」をご覧ください。

同時アクセス

複数のクライアントや複数のプロセス インスタンスによる BLOB に対する同時アクセスをサポートするには、ETag または リース を使います。

  • Etag - BLOB またはコンテナーが別のプロセスによって変更されていることを検出する手段を提供します。

  • リース - 一定期間、BLOB ストレージに対する排他的かつ更新可能な、書き込みまたは削除アクセスを取得する方法を提供します。

詳細については、「Microsoft Azure Storage でのコンカレンシーの管理」を参照してください。

名前付けコンテナー

Azure Storage のどの BLOB もコンテナーに格納する必要があります。 コンテナーは、BLOB 名の一部を形成しています。 たとえば、次の BLOB の URI のサンプルでは、 mydata がコンテナーの名前です。

  • https://storagesample.blob.core.windows.net/mydata/blob1.txt
  • https://storagesample.blob.core.windows.net/mydata/photos/myphoto.jpg

コンテナー名は有効な DNS 名で、次の名前規則に準拠している必要があります。

  1. コンテナー名は英文字または数字で始まり、英文字、数字、ダッシュ (-) 文字のみを含めることができます。
  2. すべてのダッシュ (-) 文字は、その直前または直後に文字または数字が使用されている必要があります。連続するダッシュ文字は、コンテナー名では使用できません。
  3. コンテナー名の文字はすべて小文字である必要があります。
  4. コンテナー名の長さは、3 ~ 63 文字にする必要があります。

コンテナーの名前は、常に小文字である必要があります。 コンテナー名に大文字が含まれている場合や、コンテナーの名前付け規則の他の違反がある場合、400 エラー (無効な要求) が発生することがあります。

BLOBのセキュリティ管理

既定では、Azure Storage はアカウント所有者へのアクセスを制限することによってデータのセキュリティを維持します。アカウントの所有者は、アカウント アクセス キーを所持している人です。 ストレージ アカウント内の BLOB データを共有する必要がある場合は、アカウント アクセス キーのセキュリティを損なわずに共有することが重要です。 また、ネットワーク経由の送信と Azure Storage でのセキュリティを確保するために、BLOB データを暗号化することもできます。

BLOB データへのアクセスの制御

既定では、ストレージ アカウント内の BLOB データには、ストレージ アカウント所有者だけがアクセスできます。 Blob Storage に対する認証要求には、既定ではアカウント アクセス キーが必要です。 ただし、特定の BLOB データは他のユーザーが使用できるようにしたい場合があります。

BLOB データの暗号化

Azure Storage では、クライアント側とサーバー側の両方で、BLOB データの暗号化をサポートしています。

こちらもご覧ください