normalian blog

Let's talk about Microsoft Azure, ASP.NET and Java!

Windows Azure ストレージ Blobをいじってみた

Page Blob、Block Blobの二種類が存在するBlobについてちょっとコードをまとめがてらに書いてみる。AzureTrainingKitからコードをぱくってますので、ホントに動かすコードはそちらから参照してください。

Blob コンテナの作成

Blobコンテナの作成を行っています。Blobコンテナに対するアクセス権も設定しています。

//ConnectionStringの設定
var account = CloudStorageAccount.FromConfigurationSetting("DataConnectionString");

//BlobClientの作成
var client = account.CreateCloudBlobClient();

//コンテナの参照を取得
var container = client.GetContainerReference("myContainer");
container.CreateIfNotExist();

//コンテナのアクセスをPublicに設定
var permissions = container.GetPermissions();
permissions.PublicAccess = BlobContainerPublicAccessType.Container;
container.SetPermissions(permissions);

Blobの保存

適当にBlobにデータを保存する処理を記述しました。メタデータをアタッチする処理に注意してください。

string contentType = "image/jpeg"
string blobname = "image_" + Guid.NewGuid().ToString();

//Blobの参照取得
var blob = this.GetContainer().GetBlobReference(blobname);

//コンテントタイプの設定
blob.Properties.ContentType = contentType;

//Blobに8KBまで付加できるメタデータの設定
var metadata = new NameValueCollection();
metadata["hogehoge"] = "something metadata";

//Blobにメタデータを追加
blob.Metadata.Add(metadata);

//Blobにバイトデータを格納
blob.UploadByteArray(data);

Blobの参照

Blobのメタデータを参照する場合、実はちょっとテクニックが必要です。

//Blob検索オプション?のインスタンスを生成
var blobRequestOptions = new BlobRequestOptions(){
 UseFlatBlobListing = true,
 BlobListingDetails = BlobListingDetails.All
};

//Blobの検索オプションを指定してリストを取得
this.GetContainer().ListBlobs(blobRequestOptions);

例では「BlobRequestOptions」のインスタンスを生成して、「BlobListingDetails」プロパティに"ALL"を指定してBlobのリストを生成しています。引数なしの「ListBlobs()」メソッドを実行した場合、Blobのメタデータ取得ができないという事実があったり。

Blobのその他注意点

Blobからデータを取得し、PageBlobやらBlockBlobに変換して処理を行っています。以下のコード例は「ホントにコンパイル通しただけ」の白物ですので、どうやってPageBlobとBlockBlobを取得したらよいかの参考程度に留めてください。

var blob = this.GetContainer().ListBlobs(new BlobRequestOptions()
    {
        UseFlatBlobListing = true,
        BlobListingDetails = BlobListingDetails.All
    }).OfType<CloudBlob>().FirstOrDefault();
try
{
    var pageBlob = blob.ToPageBlob;
    var length = blob.OpenRead().Length;
    //var blockSize = blob.OpenRead().BlockSize; なぜか例外が…orz
    
    //PageBlobにしかないメソッド
    //このメソッドでランダムアクセス可能?
    pageBlob.WritePages(new MemoryStream(), length);
}
catch (Exception ex)
{
    Console.Write(ex);
}
try
{
    var blockBlob = blob.ToBlockBlob;
    var length = blockBlob.OpenRead().Length;
    //var blocksize = blockBlob.OpenRead().BlockSize; なぜか例外が…orz
    blockBlob.PutBlock("blockId", new MemoryStream(), "contentMD5");//BlockBlobにしかないメソッド
}
catch (Exception ex)
{
    Console.Write(ex);
}

以下が主な疑問点

  • Blob保存時にPageやらBlockやらを決めるのでなく、Blob参照のタイミングでBlobの形式を決めるのか?
  • Page Blobが1TBまで、Block Blobが200Gまでの格納サイズ上限だったはずだけど、どこでBlobのタイプを分けて制御してるんだろう?
  • CloudPageBlobに対して、GetPageRanges()メソッドを実行したら"The blob type is invalid for this operation"と例外を吐かれた
  • CloudBlockBlob.OpenRead().BlockSize、CloudPageBlob.OpenRead().BlockSizeの値が取得できない