HTML5による複数ファイルアップロード

category-icon

 こんばんは、martinです。以前、Flex(Flash)を用いた複数ファイルのアップローダーLink を紹介しましたが、実はHTML5だけで出来るのになぁ、と思っていました。現時点で、IE8を除く主要なブラウザでは軒並み、HTML5のINPUT要素に対するmultiple属性に対応しているので、それによる実装をppBlogに施してみました。複数ファイルを選択可能にするには、input要素にmultipleを指定するだけです。

<input type="file" name="src[]" id="src" multiple />

 とりあえず実装してみただけですが、きちんと動作しました(ここのエントリーLink は画像を複数枚一度にアップロードした)。UIをどうするかで試行錯誤しましたが、プロトタイプにしてはまぁまぁかなと思っています。

shot1
このように一度に複数画像の選択が可能です。

 さて、複数の(画像)ファイルがアップロード出来るようになると、アップロードする枚数に応じて、サーバーにデータを渡す間、じっと待たされるようになります。現状、HTML5のみではぼーっと待つしかありません(-o-) なので、アップロードの進捗状況を示すプログレスバーが欲しくなります。この手のスクリプトはウェブ上にいろいろありますが、どれもFlashを用いたり、Perl(+JavaScript)を用いたりしたものです。出来ればPHP(+JavaScript)のみで完結させたい。

 いろいろ調べてみると、PHPとJavaScriptのみでは、ファイルアップロードに伴なうプログレスバーのギミックを提供するのは無理という記述ばかりです。というのもPHPには、ファイルアップロードの途中経過を知らせる仕組みが備わっていないからです。実は、PHP5.2以上であれば、PECL APC拡張機能を組み込んで可能Link なのですが、サーバー側で PECL APCエクステンションをインストールする必要があり、これはレンタルザーバー等では敷居が高いでしょう。

 なので(Perlはあまり好きになれないという理由もあり)PHPとJavaScriptのみによる実装を考えてみました。まずは、PHPにおける、POST メソッドによるファイルアップロード時の挙動を知る必要があります。マニュアルによれば、基本的に以下の手順を踏みます。
  1. サーバー上に転送される(画像)データは、最初は一時的なディレクトリ(テンポラリディレクトリ)にアップロードされます。この一時的なディレクトリは、だいたい/tmpディレクトリのことが多いです。php.iniで指定可。
  2. 画像データの転送が無事に終わると、move_uploaded_file関数を用いて指定したディレクトリに画像データを移動させます。

 PHPでのネックは、この1番目の進捗状況を知るメソッドが備わっていないことです(なのでこの部分だけはPerlで処理するスクリプトがある)。サーバーサイドで提供しないのであれば、こちらからゲットしに行きましょう。アップロード中のデータは、テンポラリディレクトリに溜まっていくので、そのディレクトリのサイズは徐々に大きくなるはずです。なので、そのディレクトリのサイズを定期的に監視すればOKということになります。この「定期的に監視」という部分にJavaScriptのAjaxを使えば良いわけです。

 ディレクトリのサイズは、以下の記述で取得可能です。
$tmp_dir = '/tmp'; // 取得したいテンポラリディレクトリ

$size = 0; // ディレクトリのサイズ

$d = opendir($tmp_dir);
while($file = readdir ($d)){
 if(is_file($tmp_dir.'/'.$file)){
  $size += filesize($tmp_dir.'/'.$file);
 }
}
closedir($d);
echo($size); // ディレクトリの合計サイズを得る

 なお、上の例では、テンポラリディレクトリは/tmpですが、これを取得したい場合は、ファイルアップロード時に現れる変数の$_FILES['src']['tmp_name']を利用して、

dirname($_FILES['src']['tmp_name']);

で取得可能です。

 あとは、AjaxとPHPで、このディレクトリサイズを返すような記述をして、それをJavaScript側に渡し、プログレスバーっぽく見せればOKとなります。具体的なデモLink を見てみましょう。うまく行けば、転送中のブラウザ画面は下のようなスクリーンショットになります。Firefox3.6.3Safari, Google Chromeの最新版で動くと思います。

progressbar
プログレスバーが表示され、進行状況が一目瞭然。

       

— posted by martin at 01:14 am   commentComment [6]  pingTrackBack [0]

この記事に対するコメント・トラックバック [6件]

scrollUp1. ちらみ — 2010/05/06@22:14:57

martinさん こんばんは。

ついに機能を付けてもらえるのですね;v)
正式リリースを心待ちにしています。

2. ポポ Website — 2010/05/11@20:32:40

はじめまして、今年の2月から使用させていただいております。感謝:)
いつも、感心ばかりしております。
複数の場合にもリサイズ機能は、今まで通り機能するのでしょうか?
楽しみにしています。
今でも充分に満足しております。
難しい言葉がでてきますので小生はあまり理解できませんが、感謝の気持ち込めて、コメントさせていただきます。

3. toshi — 2010/05/21@10:01:07

martinさん こんにちは。

コメントを承諾してから、掲載する機能を付けてもらえないでしょうか??

Owner Comment martin Website  2010/05/22@14:18:17

こんにちは。次のバージョンでそういうオプションも付けようかと思います。

5. Mu — 2010/05/31@19:27:52

martinさん はじめまして
こういったjavascript+phpだけで複数アップロードできる例がなかなか見つからなかったので助かりました
php側の処理について質問なのですが基本的には通常のアップロードの方法と同じなのでしょうか?
従来の記述ではうまいこといきませんでした。

scrollUpOwner Comment martin Website  2010/06/01@14:34:49

こんにちは。基本的には、PHPによる通常のファイルアップロード処理通りです。サンプルを配布してみました→エントリーLink

この記事に対する TrackBack URL:

設定によりTB元のページに、こちらの記事への言及(この記事へのリンク)がなければ、TB受付不可となりますのであらかじめご了承下さい。

コメントをどうぞ。 名前(ペンネーム)と画像認証のひらがな4文字は必須で、ウェブサイトURLはオプションです。

ウェブサイト (U):

タグは使えません。http://・・・ は自動的にリンク表示となります

:) :D 8-) ;-) :P :E :o :( (TT) ):T (--) (++!) ?;w) (-o-) (**!) ;v) f(--; :B l_P~

     
T: Y: ALL: Online:
Created in 0.0563 sec.
prev
2017.5
next
  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31