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 つのコンポーネントで構成されています。
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 アプリケーションに統合するプロセスは次のとおりです。
- ストレージ アカウントを作成します。 詳しくは、「ストレージ アカウントの作成」をご覧ください。
- Azure Storage クライアント ライブラリを Xamarin.Forms アプリケーションに追加します。
- ストレージの接続文字列を構成します。 詳しくは、「Azure Storage への接続」をご覧ください。
Microsoft.WindowsAzure.Storage
とMicrosoft.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 を削除します。