ファイルアップロードの進捗を表示するやつ

フォームでファイル選択してサブミットしてサーバーにファイルを送信している間に(レスポンスを待っている間に)、裏で通信してアップロードの進捗を取得して表示するというやつ。プログレスバーとか出すやつ。カッコいいなーいつかやりてーなーと思っていたのをやっとやってみた。Apache2::UploadProgressというモジュールを使った。

使い方とか

ソースを落として解凍。
ディレクトリ1個つくってその中にexamplesとextraをごっちゃにして入れる。
こんな感じで。

takatoshi@sarge:~/modperl/fileupload$ ls
css           popup.cgi     progress.jmpl     progress.js   progress.xsl
embedded.cgi  progress.css  progress.jmpl.js  progress.xsd

で、ブラウザからこのディレクトリが見えるようにしておいて、CGIも実行できるようにしておいて。
一方でApacheの設定ファイルにこれを追加。

    PerlLoadModule             Apache2::UploadProgress
    PerlPostReadRequestHandler Apache2::UploadProgress

おれはVirtualHostディレクティブの中でやったけどDirecotoryとかLocationとかFilesとかじゃないとこならどこでもいいと思う。
たぶんこれだけでオッケー。
あ、まだだ。jsとかを参照するときのパスがデフォルトだと/UploadProgress/progress.jsとかになってるんでこのへんgrepして全部置換した。

結果

これがそれなんだけど、
http://takatoshi.dyndns.org/fileupload/embedded.cgi
実際にファイルをアップしてみればわかるんだけど遅い!あり得ないくらい遅い。(ファイルは保存してないです)
プログレスバーが出るから最初はおー!とか言ってたけどよくよく考えたらこれ遅くね?って思って、別に確かめるまでもないけど確かめてみる。
http://takatoshi.dyndns.org/misc/fileupload.cgi
POSTされたらファイル名を表示してそうじゃなかったらHTMLを表示するというただそれだけ。(ファイルは保存しません)
一目瞭然の違い。
ということで、このままだとせっかくカッコいいのにプログレスバーって使えないじゃんみたいな。
ファイルサイズが大きくなったらこの差もなくなっていく(無視できる)ようになってくる気もしますが、でももうちょっとさくさくと動いてくれないと実戦では使えない。

中のほう

で、これどうやってるのかっていうとPOSTするときにJSでID発行してURLに追加してPOSTしてApache2::UploadProgressがファイルサイズを計算してメモリに保存して、その一方でXMLHTTPRequest使ってGETしてファイルサイズ確かめてプログレスバーの表示を更新してます。JSのタイマーで。
で、mod_perlモジュールって書いたことないしちゃんと読んだこともないのでよくわかんないんだけどApache2::UploadProgressのソースの先頭のほうでこんなことをやってApacheの設定追加してる模様なんだけど、すげーと思った。こんなことできるとは。

if ( $ENV{MOD_PERL} ) {

    Apache2::Module::add( __PACKAGE__, $DIRECTIVES );

    if (    Apache2::ServerUtil::restart_count() > 1
         && Apache2::Module::loaded('mod_alias.c')
         && Apache2::Module::loaded('mod_mime.c') ) {

        my $config = [
            sprintf( 'Alias /UploadProgress %s/extra', substr( __FILE__, 0, -3 ) ),
            '<Location /UploadProgress>',
            'SetHandler default-handler',
            Apache2::Module::loaded('mod_expires.c')
              ? ( 'ExpiresActive On', 'ExpiresDefault "access plus 1 day"')
              : (),
            '</Location>',
            '<Location /UpdateProgress>',
            'SetHandler modperl',
            'PerlResponseHandler Apache2::UploadProgress->progress',
            '</Location>'
        ];

        Apache2::ServerUtil->server->add_config($config);

        $HAS_BASEURI = 1;
    }
}

もっと

  • もっと早く
  • もっといろんなやり方を知りたい
  • もっと、っていうかApache 1.3系でもできるのかな?
  • もっとブラウザ対応!Safariでうまく動かない
    • -

Apache2::UploadProgress - Track the progress and give realtime feedback of file uploads - metacpan.org