Xamarin.Forms から Azure Storage にデータを格納してアクセスする

Azure Storage は、非構造化データと構造化データを保存するために使用できるスケーラブルなクラウド ストレージ ソリューションです。 この記事では、Xamarin.Forms を使ってテキストとバイナリのデータを Azure Storage に格納する方法と、データにアクセスする方法を見ていきます。

Azure Storage には、4 つのストレージ サービスがあります。

  • Blob Storage。 BLOB は、バックアップ、仮想マシン、メディア ファイル、ドキュメントなど、テキストまたはバイナリ データに使用できます。
  • Table Storage は NoSQL のキー属性ストアです。
  • Queue Storage は、ワークフロー処理とクラウド サービス間通信のためのメッセージング サービスです。
  • File Storage は、SMB プロトコルを使って共有ストレージを提供します。

ストレージ アカウントには、次の 2 種類があります。

  • 汎用ストレージ アカウントを使うと、1 つのアカウントから Azure Storage サービスにアクセスできます。
  • BLOB ストレージ アカウントは、BLOB の格納に特化したストレージ アカウントです。 BLOB データだけ格納する必要がある場合は、このアカウントの種類をお勧めします。

この記事と付随するサンプル アプリケーションでは、画像とテキスト ファイルを BLOB ストレージにアップロードし、それらをダウンロードする方法を見ていきます。 さらに、BLOB ストレージからファイルの一覧を取得し、ファイルを削除する方法も示します。

Azure Storage について詳しくは、ストレージの概要に関する記事をご覧ください。

Note

Azure サブスクリプションをお持ちでない場合は、開始する前に無料アカウントを作成してください。

Blob Storage の概要

BLOB ストレージは、次の図に示す 3 つのコンポーネントで構成されています。

Blob Storage の概念

Azure Storage へのアクセスはすべて、ストレージ アカウントを通して行われます。 ストレージ アカウントは無制限の数のコンテナーを含むことができ、コンテナーはストレージ アカウントの容量制限まで、無制限の数の BLOB を格納できます。

BLOB は、任意の種類とサイズのファイルです。 Azure Storage では、3 種類の BLOB がサポートされています。

  • ブロック BLOB は、クラウド オブジェクトのストリーミングと格納用に最適化されており、バックアップ、メディア ファイル、ドキュメントなどを格納する場合に適しています。ブロック BLOB の最大サイズは 195 GB です。
  • 追加 BLOB はブロック BLOB に似ていますが、ログなどの追加操作用に最適化されています。 追加 BLOB の最大サイズは 195 GB です。
  • ページ BLOB は、頻繁な読み取り/書き込み操作用に最適化されており、通常、仮想マシンとそのディスクを格納するために使われます。 ページ BLOB の最大サイズは 1 TB です。

Note

BLOB ストレージ アカウントでは、ブロックと追加 BLOB はサポートされていますが、ページ BLOB はサポートされていないので注意してください。

BLOB は、バイトのストリームとして、Azure Storage にアップロードされ、Azure Storage からダウンロードされます。 そのため、ファイルは、アップロードの前にバイト ストリームに変換し、ダウンロードの後で元の表現に変換して戻す必要があります。

Azure Storage に格納されているすべてのオブジェクトは、一意の URL アドレスを持っています。 ストレージ アカウント名はそのアドレスのサブドメインを形成し、サブドメインとドメイン名の組み合わせが、ストレージ アカウントの "エンドポイント" を形成します。 たとえば、ストレージ アカウントの名前が mystorageaccount の場合、ストレージ アカウントの既定の BLOB エンドポイントは https://mystorageaccount.blob.core.windows.net になります。

ストレージ アカウント内のオブジェクトにアクセスするための URL は、ストレージ アカウント内のオブジェクトの場所をエンドポイントに追加して作成します。 たとえば、BLOB アドレスは https://mystorageaccount.blob.core.windows.net/mycontainer/myblob という形式になります。

段取り

Azure Storage アカウントを Xamarin.Forms アプリケーションに統合するプロセスは次のとおりです。

  1. ストレージ アカウントを作成します。 詳しくは、「ストレージ アカウントの作成」をご覧ください。
  2. Azure Storage クライアント ライブラリを Xamarin.Forms アプリケーションに追加します。
  3. ストレージの接続文字列を構成します。 詳しくは、「Azure Storage への接続」をご覧ください。
  4. Microsoft.WindowsAzure.StorageMicrosoft.WindowsAzure.Storage.Blob 名前空間の using ディレクティブを、Azure Storage にアクセスするクラスに追加します。

Azure Storage に接続する

ストレージ アカウント リソースに対して行われるすべての要求が、認証を受ける必要があります。 匿名認証をサポートするように BLOB を構成できますが、アプリケーションがストレージ アカウントでの認証に使用できる方法は主に次の 2 つです。

  • 共有キー。 この方法では、Azure ストレージ アカウントの名前とアカウント キーを使って、ストレージ サービスにアクセスします。 ストレージ アカウントには、共有キー認証に使用できる 2 つの秘密キーが、作成時に割り当てられます。
  • Shared Access Signature. これは URL に追加できるトークンであり、それが有効な期間だけ、指定されたアクセス許可で、ストレージ リソースへの委任されたアクセを行うことができます。

アプリケーションから Azure Storage リソースにアクセスするために必要な認証情報を含む接続文字列を指定できます。 さらに、Visual Studio から Azure ストレージ エミュレーターに接続するように接続文字列を構成できます。

Note

Azure Storage では、接続文字列で HTTP と HTTPS がサポートされています。 ただし、HTTPS を使うことをお勧めします。

Azure ストレージ エミュレーターへの接続

Azure ストレージ エミュレーターで提供されるローカル環境は、開発のために Azure BLOB、キュー、テーブル サービスをエミュレートします。

Azure ストレージ エミュレーターに接続するには、次の接続文字列を使う必要があります。

UseDevelopmentStorage=true

Azure ストレージ エミュレーターについて詳しくは、「開発とテストに Azure ストレージ エミュレーターを使用する」をご覧ください。

共有キーを使用した Azure Storage への接続

共有キーを使って Azure Storage に接続するには、次の形式の接続文字列を使う必要があります。

DefaultEndpointsProtocol=[http|https];AccountName=myAccountName;AccountKey=myAccountKey

myAccountName はストレージ アカウントの名前に置き換え、myAccountKey は 2 つのアカウント アクセス キーのいずれかに置き換える必要があります。

Note

共有キー認証を使う場合は、アプリケーションを使う各ユーザーにアカウント名とアカウント キーを配布します。これにより、ストレージ アカウントへの完全な読み取り/書き込みアクセスが提供されます。 そのため、共有キー認証はテストのためにのみ使用し、他のユーザーにキーを配布しないでください。

Shared Access Signature を使用した Azure Storage への接続

SAS を使って Azure Storage に接続するには、次の形式の接続文字列を使う必要があります。

BlobEndpoint=myBlobEndpoint;SharedAccessSignature=mySharedAccessSignature

myBlobEndpoint は BLOB エンドポイントの URL に置き換え、mySharedAccessSignature は SAS に置き換える必要があります。 SAS は、リソースにアクセスするためのプロトコル、サービス エンドポイント、資格情報を提供します。

Note

運用アプリケーションには SAS 認証をお勧めします。 ただし、運用アプリケーションでの SAS は、アプリケーションにバンドルするのではなく、オンデマンドでバックエンド サービスから取得する必要があります。

Shared Access Signature について詳しくは、Shared Access Signature (SAS) の使用に関する記事をご覧ください。

コンテナーの作成

GetContainer メソッドを使って名前付きコンテナーへの参照を取得した後、それを使って、コンテナーから BLOB を取得したり、コンテナーに BLOB を追加したりできます。 次のコード例は、GetContainer メソッドを示しています。

static CloudBlobContainer GetContainer(ContainerType containerType)
{
  var account = CloudStorageAccount.Parse(Constants.StorageConnection);
  var client = account.CreateCloudBlobClient();
  return client.GetContainerReference(containerType.ToString().ToLower());
}

CloudStorageAccount.Parse メソッドは接続文字列を解析し、ストレージ アカウントを表す CloudStorageAccount インスタンスを返します。 その後、コンテナーと BLOB の取得に使われる CloudBlobClient インスタンスを、CreateCloudBlobClient メソッドで作成します。 GetContainerReference メソッドは、指定されたコンテナーを CloudBlobContainer インスタンスとして取得してから、呼び出し元のメソッドに返します。 この例では、コンテナーの名前は ContainerType 列挙値を小文字の文字列に変換したものでです。

Note

コンテナー名は小文字でなければならず、文字または数字で始まっている必要があります。 また、文字、数字、ダッシュ文字のみを使用でき、長さは 3 から 63 文字にする必要があります。

GetContainer メソッドは次のように呼び出されます。

var container = GetContainer(containerType);

その後、コンテナーがまだ存在しない場合は、CloudBlobContainer インスタンスを使って作成できます。

await container.CreateIfNotExistsAsync();

既定では、新しく作成されるコンテナーはプライベートです。 つまり、コンテナーから BLOB を取得するには、ストレージ アクセス キーを指定する必要があります。 コンテナー内の BLOB をパブリックにする方法については、「コンテナーの作成」をご覧ください。

コンテナーへのデータのアップロード

バイト データのストリームを BLOB ストレージにアップロードするには、次のコード例で示すように、UploadFileAsync メソッドを使います。

public static async Task<string> UploadFileAsync(ContainerType containerType, Stream stream)
{
  var container = GetContainer(containerType);
  await container.CreateIfNotExistsAsync();

  var name = Guid.NewGuid().ToString();
  var fileBlob = container.GetBlockBlobReference(name);
  await fileBlob.UploadFromStreamAsync(stream);

  return name;
}

このメソッドは、コンテナーの参照を取得した後、コンテナーがまだ存在しない場合は作成します。 その後、一意の BLOB 名として機能する新しい Guid が作成され、BLOB ブロックの参照が CloudBlockBlob インスタンスとして取得されます。 それから、データのストリームが、UploadFromStreamAsync メソッドを使って BLOB にアップロードされます。BLOB がまだ存在しない場合は作成され、存在する場合は上書きされます。

このメソッドを使って BLOB ストレージにファイルをアップロードする前に、まずそれをバイト ストリームに変換する必要があります。 次のコード例ではこれを見ていきます。

var byteData = Encoding.UTF8.GetBytes(text);
uploadedFilename = await AzureStorage.UploadFileAsync(ContainerType.Text, new MemoryStream(byteData));

text データは、バイト配列に変換された後、UploadFileAsync メソッドに渡されるストリームとしてラップされます。

コンテナーからのデータのダウンロード

BLOB データを Azure Storage からダウンロードするには、次のコード例で示すように、GetFileAsync メソッドを使います。

public static async Task<byte[]> GetFileAsync(ContainerType containerType, string name)
{
  var container = GetContainer(containerType);

  var blob = container.GetBlobReference(name);
  if (await blob.ExistsAsync())
  {
    await blob.FetchAttributesAsync();
    byte[] blobBytes = new byte[blob.Properties.Length];

    await blob.DownloadToByteArrayAsync(blobBytes, 0);
    return blobBytes;
  }
  return null;
}

コンテナー参照を取得した後、このメソッドは格納されているデータの BLOB 参照を取得します。 BLOB が存在する場合は、FetchAttributesAsync メソッドでそのプロパティを取得します。 正しいサイズのバイト配列が作成され、バイトの配列として BLOB がダウンロードされて、呼び出し元のメソッドに返されます。

ダウンロードした後で、BLOB バイト データを元の表現に変換する必要があります。 次のコード例ではこれを見ていきます。

var byteData = await AzureStorage.GetFileAsync(ContainerType.Text, uploadedFilename);
string text = Encoding.UTF8.GetString(byteData);

GetFileAsync メソッドで Azure Storage からバイトの配列を取得した後、UTF8 エンコード文字列に変換して戻します。

コンテナー内のデータ一覧の取得

コンテナーに格納されている BLOB の一覧を取得するには、次のコード例で示すように、GetFilesListAsync メソッドを使います。

public static async Task<IList<string>> GetFilesListAsync(ContainerType containerType)
{
  var container = GetContainer(containerType);

  var allBlobsList = new List<string>();
  BlobContinuationToken token = null;

  do
  {
    var result = await container.ListBlobsSegmentedAsync(token);
    if (result.Results.Count() > 0)
    {
      var blobs = result.Results.Cast<CloudBlockBlob>().Select(b => b.Name);
      allBlobsList.AddRange(blobs);
    }
    token = result.ContinuationToken;
  } while (token != null);

  return allBlobsList;
}

コンテナー参照を取得した後、このメソッドはコンテナーの ListBlobsSegmentedAsync メソッドを使って、コンテナー内の BLOB への参照を取得します。 BlobContinuationToken インスタンスが null になるまで、ListBlobsSegmentedAsync メソッドによって返される結果を列挙します。 各 BLOB は、allBlobsList コレクションに値が追加される前に、BLOB の Name プロパティにアクセスするため、返された IListBlobItem から CloudBlockBlob にキャストされます。 BlobContinuationToken インスタンスが null になったら、最後の BLOB 名が返されたので、実行はループを終了します。

コンテナーからのデータの削除

コンテナーから BLOB を削除するには、次のコード例で示すように、DeleteFileAsync メソッドを使います。

public static async Task<bool> DeleteFileAsync(ContainerType containerType, string name)
{
  var container = GetContainer(containerType);
  var blob = container.GetBlobReference(name);
  return await blob.DeleteIfExistsAsync();
}

コンテナー参照を取得した後、このメソッドは指定された BLOB の BLOB 参照を取得します。 その後、DeleteIfExistsAsync メソッドで BLOB を削除します。