アルファサード株式会社 代表取締役 野田 純生のブログ


Net::Azure::StrageClientモジュールを書いてCPANデビューした話。


公開日 : 2013-12-19 00:00:01


この記事はPerl Advent Calendarの19番目のエントリーです。

Net::Azure::StorageClient モジュールを作ってCPANデビューしました。

11月に Net::Azure::StorageClient というモジュールを作って、CPANデビューしました。Azureの Advent Calendar でこのモジュールの紹介をしようと思っていたのですが、Mac用クライアントを作ったのでそっちの話題にしてしまったので、こっち(どっちだ)に書こうかと。

モジュールの利用方法

use Net::Azure::StorageClient::Blob;
my $blobService = Net::Azure::StorageClient::Blob->new(
                                    account_name => $you_account_name,
                                    primary_access_key => $your_primary_access_key,
                                    container_name => $container_name, );
my $path = 'path/to/blob';
my $res = $blobService->get_blob( $path );

戻り値は HTTP::Response object(s)です。 詳細はドキュメントを見ていただくとして、Azure Blob APIにある一通りの機能は実装してあります。それ以外にいくつか便利なものが。例えばダウンドードはこんな感じで

my $res = $blobService->download( $container . '/' . $path, $local_path, $params );

アップロードは以下のようになります。

my $res = $blobService->upload( $container . '/' . $path, $local_path, $params );

download/upload は実はフォルダ指定にも対応しています。downloadは、コンテナ指定もできます。

マルチスレッドによる高速ダウンロード/アップロード

Threadが利用可能な時、ディレクトリを指定するときに、$params に { use_thread => 10 } を与えるとマルチスレッド(スレッド数の上限が10)で高速に処理を実行できます。

Windows Azure Blob APIのいくつかのTips

せっかくなので、ハマったこととか、ドキュメントがなくて悩んだことなどを。何せ、書籍も古いものしかないので(買ったけど)。

ディレクトリの扱い

ディレクトリ以下のBlob一覧を得るには、リクエストに prefix=パスの開始文字 を追加します(厳密にはディレクトリという概念はないのですが、例えばパスに / のような文字列を指定して擬似的にディレクトリのように扱うことができます)。

my $res = $blobService->list_blobs( $container_name, { options => 'prefix=directory_name/' } );

この時、ディレクトリ直下のアイテムのみを得るには(そうでないと、大量のコンテンツを含む上位ディレクトリほど処理が重くなる)、delimiterオプションを付与します(大量のコンテンツのある上位ディレクトリの表示にCloudXplorerとかめっちゃ速くてどうやってんだろ、これみたいなことで英文の技術ブログなんか読みあさって試行錯誤して発見したのでした...)。

my $res = $blobService->list_blobs( $container_name, { options => 'delimiter=/&prefix=directory_name/' } );

5000件を超えるBlobのリスト取得

my $res = $blobService->list_blobs( $container_name );

とすると、コンテナ以下のBlobの一覧を取得しますが、5000件の制限があります。5000件を超える場合、取得したXMLに NextMarker という要素があるので、この値を marker パラメタに渡してやります。

my $res = $blobService->list_blobs( $container_name, { options => 'marker=' . $marker } );

この時、$NextMarker をURLエンコードしてやらないといけません。というか、エンコードしないとあかん文字列がAPIから返ってくるのでした。

my @responses;
my $res = $blobService->list_blobs( $container_name );
push ( @responses, $res );
my $xml = XML::Simple->new;
my $data = $res->content;
my $list = $xml->XMLin( $data );
$marker = $list->{ NextMarker };
$marker = undef if ( ( ref $marker ) eq 'HASH' );
while ( $marker ) {
    $marker =~ s!([^a-zA-Z0-9_.~-])!uc sprintf "%%%02x", ord($1)!eg;
    $res = $blobService->list_blobs( $container_name, { options => 'marker=' . $marker } );
...

Net::Azure::StrageClient::Blobのlist_blobsでは、この辺りの処理は自動的にやってくれます。 冒頭に「HTTP::Response object(s)です。」と書きましたが、(s)というのは、list_blobs等の場合は自動的に再帰的にリクエストを送って HTTP::Response object の配列を返すようにしているからです。

といった感じで、これ、PerlからAzureのBlobを扱うのに便利なモジュールですよ。

カテゴリ


このブログを書いている人
野田純生の写真
野田 純生 (のだ すみお)

大阪府出身。ウェブアクセシビリティエバンジェリスト。 アルファサード株式会社の創業者であり、現役のプログラマ。経営理念は「テクノロジーによって顧客とパートナーに寄り添い、ウェブを良くする」。 プロフィール詳細へ