概説
<input type="file" multiple>
で複数ファイルを同時に選択して送信することが可能ですが、ここでは以下のようなディレクトリ構造を丸ごと送信する方法を説明します。
top
├ test.html
└─ second
├─ test.html
└─ third
└─ test.html
やり方
webkitdirectory属性を指定するだけ。ただし、ベンダープレフィックスがついていることから分かるように今のところこの指定方法はChromeでのみ動作するようです。将来的にはベンダープレフィックスが外れて、<input type="file" directory>
のようになるんだと思います。
<input type="file" name="upfile[]" webkitdirectory>
サーバー側(PHP)ではどのように値が渡ってくるのか?
<input type="file" name="upfile[]" webkitdirectory>
のファイル選択画面で↑で説明したディレクトリの「top」を選択して送信した場合、$_FILESには以下のように値が渡ってきます。
array (
0 => 'test.html',
1 => 'test.html',
2 => 'test.html',
)
array (
0 => '/tmp/phpaNxASP',
1 => '/tmp/php5yTfGo',
2 => '/tmp/phpT2sVtX',
)
なお、<input type="file" multiple>
で複数ファイルを送信した場合も同じような形式で情報が渡ってきます。
注意点は以下の2点
- $_FILES['upfile']['name']にはファイル名のみが渡ってくるため、同名ファイルの場合に区別がつかない。
- 階層構造の情報は渡ってこない。
階層構造の情報を送信したい場合
クライアント側で「webkitRelativePath」というファイルオブジェクトのプロパティが取得可能なので、これをPOSTデータに含めて一緒に送信し、サーバー側でゴニョゴニョしてあげると良いと思います。
php.iniでの注意点
アップロード時にディレクトリを指定するということは、たくさんのファイルを同時に送信することが可能ということですので、php.iniの最大サイズやファイル数の上限などの設定値に注意しておく必要があります。
; Maximum allowed size for uploaded files.
upload_max_filesize = 2M
; Maximum number of files that can be uploaded via a single request
max_file_uploads = 20
ファイルの総サイズについては、「$_FILES['upfile']['size']」の配列のすべての値を加算することで算出可能です。
また、総ファイル数をチェックする場合は、「count($_FILES['upfile']['name'])」のように配列の要素数で確認できます。