Python+tweepy+web.py+Azureストレージで作るTwitter連携アプリケーション 3ページ

作成するファイルアップローダの概要

 今回紹介するサンプルプログラムは、指定したファイルをBlobストレージ内に格納するという、いわゆる「アップローダ」などと呼ばれるものだ(図6)。一般的なアップローダと同様、アップロードするファイルはWebページ内のフォームで指定する。また、アップロードしたユーザーを識別するための文字列も入力できるようになっている。

図6 今回作成した簡易ファイルアップローダ
図6 今回作成した簡易ファイルアップローダ

 このアップローダは、表4のファイルから構成されている。

表4 簡易ファイルアップローダの構成ファイル
ファイル名 説明
uploader.html アップロード用のフォームを含むHTMLファイル
upload.php アップロードされたファイルをBlobストレージに保存するPHPスクリプト
list.php Blobストレージに保存されたファイルの一覧を表示するPHPスクリプト
main.css 上記3ファイルから共通して呼び出されるCSSファイル

 「uploader.html」はアップローダのトップページとなるHTMLファイルで、アップロードするファイルを指定するためのフォームや、ファイルリストを表示するページ(list.php)へのリンクを含んでいる(リスト1)。

リスト1 アップロードフォームを含む「uploader.html」(抜粋)

	<div>
	<h1>File Uploader with PHP & Windows Azure</h1>
	<h2>Upload:</h2>
	<form action="upload.php" method="post" enctype="multipart/form-data">  ……①
	  <label>file:
      <input type="file" name="upload_file" size="20">  ……②
	  </label>
	  <label>uploaded by:
	  <input type="text" name="uploaded_by" size="20">  ……③
	  </label>
	  <input type="submit" value="Upload">
	</form>
  </div>

  <div>
	<a href="list.php">Show uploaded file list</a>
  </div>

 フォームでは「upload.php」に対しPOST操作でファイルを送信するよう指定し(①)、アップロードするファイルを指定するテキストボックス(②)と、名前等を入力できるテキストボックス(③)を用意した。

 アップロードされたファイルは、「upload.php」PHPスクリプト内で処理される。ここではまずBlobに対するラッパークラスを提供している「Microsoft/WindowsAzure/Storage/Blob.php」ファイルを読み込み、いくつかの変数を定義している。

リスト2 アップロードされたファイルを処理する「upload.php」(抜粋):Blob.phpの読み込みと環境設定部分

require_once('Microsoft/WindowsAzure/Storage/Blob.php');

// upload.htmlのパス
$root_url = '/uploader/uploader.html';

// BlobにアクセスするためのベースURL
$blob_baseurl = 'blob.core.windows.net';

// Azure Storageのアカウント名およびアクセスキー
$storage_account = '<アカウント名>';
$storage_accesskey = '<アクセスキー>';

// アップロード先コンテナ名
$container_name = 'phpuploader';

 upload.php内ではまた、Blobストレージへのアップロードを行うupload2azure関数も定義している(リスト3)。この関数にはアップロード先コンテナ名、ファイル名、アップロードするファイルのパス、アップロード主を示すテキストの4つを引数として指定する。

リスト3 アップロードされたファイルを処理する「upload.php」(抜粋):upload2azure関数の定義部分

function upload2azure($container, $filename, $filepath, $uploaded_by) {
    global $storage_account, $storage_accesskey, $blob_baseurl;

    // ①接続クライアントクラスのインスタンスを作成
    $blob_client = new Microsoft_WindowsAzure_Storage_Blob(
        $blob_baseurl, $storage_account, $storage_accesskey);
    // ②コンテナを作成しACLを「Blobのみ公開」に変更
    $blob_client->createContainerIfNotExists($container);
    $blob_client->setContainerAcl($container,
                                  Microsoft_WindowsAzure_Storage_Blob::ACL_PUBLIC_BLOB);

    // ③メタデータに追加情報を格納
    $meta_data = array();
    if ($uploaded_by != "") {
        $meta_data["uploadedby"] = $uploaded_by;
    }
    $blob_name = $filename;

    // ④Blobにファイルをアップロード
    $blob_client->putBlob($container, $blob_name,
                          $filepath, $meta_data);

    // ⑤アップロード先URLを作成
    $url = "http://{$storage_account}.{$blob_baseurl}/{$container}/{$blob_name}";
    return $url;
}

 関数内ではまずBlobストレージへのアクセスを行うMicrosoft_WindowsAzure_Storage_Blobクラスのオブジェクトを作成し(①)、続いてコンテナの作成とコンテナのACL(アクセス許可リスト)の設定を行っている(②)。ここではコンテナ内のBlob に対し認証無しのアクセスを許可したいので、「ACL_PUBLIC_BLOB」(Blobに限定して匿名読み取りを許可)を指定している。

 続いてputBlob関数を呼び出し、Blobストレージにファイルをアップロードする(④)。pubBlob関数の引数は次のようになっている。

putBlob(<コンテナ名>,<Blob名>,<アップロードするファイルのパス>,<付加するメタデータ>)

 メタデータはPHPのArray形式で指定するが、ここでは$uploaded_by引数で与えた文字列を「uploadedby」という名称のメタデータとして付与している(③)。

 アップロードに成功すると、そのファイルには「http://<ストレージアカウント名>.blob.core.windows.net/<コンテナ名>/<Blob名>」というURLでアクセスできるようになる。upload2azureは戻り値としてこのURL文字列を返すようにしている(⑤)。

 upload2azure関数を呼び出してファイルをアップロードする処理はリスト4のようになっている。アップロードされたファイルの存在を確認したうえで、アップロード主の情報(テキストボックスに入力されたテキスト)があればそれをURLエンコードし(①)、これらの情報をupload2azure関数に渡してアップロードを行っている。

リスト4 アップロードされたファイルを処理する「upload.php」(抜粋):upload2azure関数の呼び出し部分

if (is_uploaded_file($_FILES["upload_file"]["tmp_name"])) {
    $filename = $_FILES["upload_file"]["name"];
    $filepath = $_FILES["upload_file"]["tmp_name"];
    $uploaded_by = "";

    // ①アップロード主(uploaded_by)はURLエンコードして保存
    if (array_key_exists("uploaded_by", $_POST)) {
        $uploaded_by = urlencode($_POST["uploaded_by"]);
    }
    $url = upload2azure($container_name, $filename, $filepath, $uploaded_by);
    echo "<p>Upload succeeded.</p>";
    echo "<p>URL is: <a href='{$url}'>$url</a></p>";

 uploader.htmlから実際にファイルをアップロードした行った結果は図7のようになる。今回はBlobに対する認証無しでのアクセスを許可しているので、ここで表示されるBlobのURLをクリックすればそのままそのファイルをダウンロードできる。

図7 ファイルのアップロード結果
図7 ファイルのアップロード結果

 続いて、アップロードしたファイルの一覧表示を行う「list.php」を見てみよう。ファイル一覧の取得はファイル中のget_filelist関数で行っている(リスト5)。

リスト5 ファイル一覧表示を行う「list.php」(抜粋):ファイル一覧を取得するget_filelist関数部分

function get_filelist($container) {
    global $storage_account, $storage_accesskey, $blob_baseurl;

    // ①接続クライアントクラスのインスタンスを作成
    $blob_client = new Microsoft_WindowsAzure_Storage_Blob(
        $blob_baseurl, $storage_account, $storage_accesskey);
    // ②コンテナの作成
    $blob_client->createContainerIfNotExists($container);

    // ③コンテナ内のBlob一覧をメタデータ付きで取得
    $blobs = $blob_client->listBlobs($container, "", "", null, null, "metadata");
    return $blobs;
}

 Blobへのアクセスにはupload.phpと同様、Microsoft_WindowsAzure_Storage_Blobクラスを利用している。関数内ではこのオブジェクトを作成し(①)、もしコンテナが作成されていない場合でもエラーとならないようコンテナの作成を行っている(②)。コンテナ内のBlob一覧を取得しているのがlistBlobs関数だ(③)。これは次のように定義されている。

array listBlobs( [string $containerName = ''], [string $prefix = ''], [string $delimiter = ''], [int $maxResults = null], [string $marker = null], [string $include = null], [int $currentResultCount = 0])

 listBlobの動作は、基本的には第1引数で指定したコンテナに含まれるBlob情報をArray型で返す、というシンプルなものだ。また、「$include」引数に「metadata」を指定することで、Blob情報に加えてそのメタデータも同時に取得できる。

 get_filelist関数ではlistBlobsの返り値をそのまま返しているが、そこから実際のファイル情報を表示する部分がリスト6である。

リスト6 ファイル一覧表示を行う「list.php」(抜粋):listBlobsの結果を元に一覧表示を行う部分

$blobs = get_filelist($container_name);

// ①ヘッダを出力
echo "<h1>File list</h1>\n";
echo "<table><tbody>\n";
echo "<tr><th>File Name</th><th>URL</th><th>Uploaded by</th><th>Upload time</th></tr>\n";
echo "</tr>\n";

// ②一覧表示を行う
foreach ($blobs as $blob) {
    $uploaded_by = "";
    if (array_key_exists("uploadedby", $blob->Metadata)) {
        $uploaded_by = htmlspecialchars(urldecode($blob->Metadata["uploadedby"]), ENT_QUOTES, "UTF-8");
    }
    $filename = htmlspecialchars($blob->Name, ENT_QUOTES, "UTF-8");
    $url = "http://{$storage_account}.{$blob_baseurl}/{$container_name}/{$filename}";

    echo "<tr><td>$filename</td><td><a href='$url'>$url</td></td><td>$uploaded_by</td><td>$blob->LastModified</td></tr>\n";
}

// ③フッタを出力
echo "</tbody></table>\n";

 今回はHTMLのテーブルを用いて表示を行っているので、まず①の個所でそのためのHTMLを出力している。次に、②のforeachループ内でget_filelist関数で得られた配列を順に取り出し、その情報をテーブルの要素として書き出している。たとえばBlob名は「$blob->Name」で、最終更新時は「$blob->LastModified」としてアクセスできる。また、メタデータは「$blob->Metadata」連想配列内に格納されている。最後に、③の部分でフッタを出力して完了だ。実行結果は図8のようになる。

図8 list.phpの実行結果
図8 list.phpの実行結果

 このように、Blobストレージはラッパークラスを利用すれば大きな手間もかからず、ローカルのファイルにアクセスする場合とほぼ同様に利用できる。適切にアクセス権を設定すれば、直接Webブラウザなどのクライアントからファイルを取得できるのもメリットだ。

 なお、このソースコード全文はSourceForge.JPの個人レポジトリサービス「PersonalForge」および「Windows Azure記事サンプルコード」で公開している。