PHP5.4の新機能の一つ: アップロード進捗の取得
PHP5.4 Advent Calendarの13日目です。@co3kさんの記事に引き続き、PHP5.4の新しい機能を紹介します。
PHP5.4で見逃せない新機能の1つとして、今までPHP単体では出来なかったファイルのアップロードの進捗情報が取得できるようになりました。今までアップロードの進捗情報は、APCやFlashなどを利用しなければ取得できないものでした。この記事では実際に動くサンプルコードと共にこの機能を紹介します。
導入
以下のようなファイルアップロードのためのフォームを用意します。この時パラメータにsession.upload_progress.nameディレクティブのエントリを追加します。これはアップロードの進捗情報を取得するという宣言で、これが無いと進捗は保存されないので注意です。この例では、"example"という値をつけています。
<?php session_start() ?> <form action="upload.php" target="hoge" method="POST" enctype="multipart/form-data"> <input type="hidden" name="<?php echo ini_get("session.upload_progress.name"); ?>" value="example" /> <input id="file1" type="file" name="file1" /> <input type="submit" value="upload" /> </form>
以上のフォームから何かでっかいファイルをアップロードすると、セッション内にアップロードの進捗が設定されるようになります。アップロードしつつ、以下のプログラムにアクセスすると、進捗情報がダンプされます。
<?php session_start(); $key = ini_get("session.upload_progress.prefix") . "example"; var_dump($_SESSION[$key]);
session.upload_progress.prefixディレクティブ + 先ほどつけた"example" というキーでセッション中に進捗情報が保存されます。上の例だと以下のように設定されます。
array(5) { ["start_time"]=> int(1323713434) ["content_length"]=> int(155908) ["bytes_processed"]=> int(155908) ["done"]=> bool(true) ["files"]=> array(1) { [0]=> array(7) { ["field_name"]=> string(5) "file1" ["name"]=> string(13) "APC-3.1.9.tgz" ["tmp_name"]=> string(22) "/private/tmp/phpeMGDne" ["error"]=> int(0) ["done"]=> bool(true) ["start_time"]=> int(1323713434) ["bytes_processed"]=> int(155540) } } }
各種情報が保存されていることがわかると思います。100 * (content_lengthパラメータ / byte_processedパラメータ) で、アップロード全体がどれぐらい進んだかをパーセントで求められます。また、各ファイルごとの進捗もここで取得することができます。
実際に進捗付きのアップロードフォームを作る場合は、Ajaxで進捗を取得して表示することになると思います。以下はjQueryを使って進捗を%で表示する例です。
<?php // index.php session_start(); ?><html><head></head> <body> <form action="index.php" method="POST" enctype="multipart/form-data"> <input type="hidden" name="<?php echo ini_get("session.upload_progress.name"); ?>" value="example" /> <input id="file1" type="file" name="file1" /> <input type="submit" value="upload" /> <span id="progress">0%</span> </form> <script type="text/javascript" src="http://code.jquery.com/jquery-1.7.1.min.js"></script> <script type="text/javascript"> $(function() { $("form").submit(function() { var progress = $("#progress"); var f = function() { $.getJSON("./progress.php", function(data) { console.dir(data); if (data != null) { progress.text( "" + Math.round(100 * (data["bytes_processed"] / data["content_length"])) + "%" ); if (!data["done"]) { setTimeout(f, 200); } } }); }; setTimeout(f, 300); }); }); </script> </body></html>
<?php # progress.php session_start(); $key = ini_get("session.upload_progress.prefix") . 'example'; echo isset($_SESSION[$key]) ? json_encode($_SESSION[$key]) : json_encode(null);
以下はサンプルを作成した際にphp.iniに追加で設定したディレクティブです。
upload_max_filesize = 2000M error_reporting = E_ALL session.upload_progress.min_freq = 0.000000001 session.upload_progress.cleanup = off post_max_size = 2000M memory_limit = 2000M
各種ディレクティブは、実際に本番で利用する際は適切に設定して下さい。特にsession.upload_progress.cleanupはセッション中にゴミを残さないようにonにしたほうがいいと思います。
終わり
というわけで、PHP5.4のファイルアップロードの進捗を取得するコードを紹介しました。次は@tpyamamotoさんお願いいたしますー。