随分前に「<input type="file">でディレクトリを丸ごと送信したい」という記事を書いたんですが、この時点ではディレクトリ構造をサーバー側で受け取るには送信時にクライアント側で別途対応する必要があり少々面倒でした。
PHP 8.1.0がリリースされ、その新機能の中でスーパーグローバルの $_FILES
に full_path
という項目が追加されました。これによりアップロードしたファイルのディレクトリ構造の情報を取得することができるようになりました。
- 参考URL
実際に試してみるためにいくつか準備を行います。
まずは、「<input type="file">でディレクトリを丸ごと送信したい」の記事の際に利用したものと同じ構成ですが、以下のようなファイル群を準備します。
top
├ test.html
└─ second
├─ test.html
└─ third
└─ test.html
次にファイルをアップロードするための画面となる index.html
を準備します。
<html>
<body>
<form action="upload.php" method="post" enctype="multipart/form-data">
<input type="file" name="upfile[]" webkitdirectory>
<input type="submit" />
</form>
</body>
</html>
アップロード時に $_FILES
の中身を確認するための upload.php
を準備します。
<?php
var_dump($_FILES['upfile']['name']);
var_dump($_FILES['upfile']['tmp_name']);
var_dump($_FILES['upfile']['full_path']);
動かす環境は何でもよいのですが、今回はDockerを利用することにしました。
まずは PHP7.4系 の最新バージョンである 7.4.27 を起動して、上記の index.html
と upload.php
を配置します。
$ docker container run -it -p 8080:8080 --rm php:7.4.27-cli /bin/bash
次に、Dockerコンテナ内でビルトインサーバーを起動します。
# php -S 0.0.0.0:8080
ブラウザで http://localhost:8080/ にアクセスすると、以下のような画面が表示されるかと思います。
「ファイル選択」ボタンから事前に準備しておいたファイル群の「top」ディレクトリを選択して「送信」ボタンをクリックします。
PHP7.4系なので、 $_FILES
の name
と tmp_name
の内容は確認できますが、未対応の full_path
の中身は NULL
となっています。
array(3) {
[0]=>
string(9) "test.html"
[1]=>
string(9) "test.html"
[2]=>
string(9) "test.html"
}
array(3) {
[0]=>
string(14) "/tmp/php0xAVds"
[1]=>
string(14) "/tmp/phpcGnajr"
[2]=>
string(14) "/tmp/phpTOKfVq"
}
NULL
それでは本題の PHP8.1系 の最新バージョンの 8.1.1 を起動して、同様にアップロード画面からファイル群を送信してみます。
% docker container run -it -p 8080:8080 --rm php:8.1.1-cli /bin/bash
PHP8.1系では $_FILES
の full_path
対応しているので、今度は送信したファイル群のディレクトリ構造の情報が取得できました。
array(3) {
[0]=>
string(9) "test.html"
[1]=>
string(9) "test.html"
[2]=>
string(9) "test.html"
}
array(3) {
[0]=>
string(14) "/tmp/phpIXmVWi"
[1]=>
string(14) "/tmp/phpupEHqh"
[2]=>
string(14) "/tmp/phpeCYwdi"
}
array(3) {
[0]=>
string(13) "top/test.html"
[1]=>
string(20) "top/second/test.html"
[2]=>
string(26) "top/second/third/test.html"
}