APC と jQuery を利用してファイルアップロードの進行状況を表示する
2008-04-13-2: [PHP][jQuery][JavaScript]
			  ネタ的には特別新しいものではないですが、気になっていたので試してみました。
  PHP 5.2.0 以降、APC 3.0.13 が必要です。
1. APC の設定
  普通に APC をインストールして、以下のように apc.rfc1867 を有効にするだけです。
apc.rfc1867 = On
2. アップロードフォームの準備
  普通のアップロードフォームです。
  ただし、"APC_UPLOAD_PROGRESS" という name 属性を持った hidden フィールドを用意します。値は、何でもいいのですが、ここでは "progress_key" という風にしています (本当はランダムにするほうがいいと思います)。
<form id="upload" action="upload.php" method="post" enctype="multipart/form-data">
<p>
<input type="hidden" name="APC_UPLOAD_PROGRESS" value="progress_key" />
<input type="file" name="file" />
<input id="submit_button" type="submit" value="アップロード" />
</p>
</form>
3. アップロードファイルの処理
  上記アップロードフォームの upload.php ですが、これは通常のファイルアップロード時の処理を書いてください。
  今回はテストなので何もしませ
<?php
// 通常のファイルアップロードの処理
?>
4. アップロードの進行状況を返す処理
  次のファイルを progress.php とします。
<?php
// progress.php
header('Content-type: application/json; charset=UTF-8');
$status = apc_fetch('upload_progress_key');
echo json_encode($status);
exit;
?>
  2 で指定した "APC_UPLOAD_PROGRESS" の値の先頭に upload_ をつけたものを apc_fetch() の引数に指定します。upload_ は設定で変更することが出来ます (apc.rfc1867_prefix)。
  apc_fetch() で取得できる値は次のようになります。
| total | アップロードされるファイルのサイズ | |
| current | 現時点までに受信したファイルのサイズ | |
| rate | アップロード速度 (byte/second) | アップロード完了時のみ | 
| filename | ファイル名 | |
| name | <input type="file" /> の name 属性 | |
| temp_filename | 一時ファイル名 | アップロード完了時のみ | 
| cancel_upload | アップロードがキャンセルされたかどうか | アップロード完了時のみ | 
| done | アップロードが完了したかどうか | |
| start_time | アップロード開始日時の UNIX TIME | 
- cancel_upload: 0 = キャンセルされていない、1 = キャンセルされた
 - done: 0 = 未完了、1 = 完了
 
  これらの値を JSON で出力しています。
5. jQuery を使って進行状況を取得する
  jQuery Form Plugin を使って、フォームを POST し、1 秒毎に getJSON で進行状況を取得します。
  また、getJSON でリクエストに現在日時を渡しているのは、ブラウザのキャッシュを利用しないようにするためです。
var timer = null;
var progress = function() {
    // progress.php を呼び出して進行状況を取得する
    $.getJSON('progress.php', { 'd': new Date().getTime() }, function(json) {
        // 進行状況を % で表示する
        $('#status').html(parseInt(json.current / json.total * 100) + '%');
    });
};
$(function() {
    $('#upload').submit(function() {
        timer = setInterval('progress()', 1000);
        // フォームを POST する
        $(this).ajaxSubmit(function() {
            clearInterval(timer);
            progress();
        });
        return false;
    });
});
6. デモ
  本当は、デモを用意したかったのですが、ここのレンタルサーバでは APC が使えないようでしたのでアップロード状況をキャプッチャしました。
  基本的には、上記の処理を行なっているだけですが、進行状況の表示の部分は Progress Bar Plugin を利用して、プログレスバーで表示しています。
	
	
  このデモで使用したファイル一式を以下に置いておきます。
参考
- PHP V5.2 の新機能、第 5 回: ファイル・アップロードの進行状況を追跡する方法
  http://www.ibm.com/developerworks/jp/opensource/library/os-php-v525/
- upload meter for PHP with APC and Json
  http://progphp.com/progress.phps
- PHP: APC 関数 - Manual
  http://php.net/apc
- jQuery Form Plugin
  http://malsup.com/jquery/form/
- Progress Bar Plugin
  http://digitalbush.com/projects/progress-bar-plugin
			
			
