第 19 章 ファイルアップロードの処理

目次
POST メソッドによるアップロード
陥りやすい落とし穴
複数ファイルのアップロード
PUT メソッドのサポート

POST メソッドによるアップロード

PHP は、全てのRFC-1867対応ブラウザ(Netscape Navigator 3 以上、 MicrosoftからのパッチをあてたMicrosoft Internet Explorer 3または パッチ無しのそれ以降の版を含みます)からファイルのアップロードを 受けることができます。 この機能では、テキストとバイナリファイルの両方のアップロードが可能です。 PHPの認証機構およびファイル操作関数を用いて、アップロードを許可する ユーザーとアップロード後にそのファイルを使用して行う動作を完全に制御する ことが可能です。

PHPはNetscape ComposerおよびW3CのAmayaクライアントにより使用される PUTメソッドによるファイルアップロードもサポートしていることに注意 して下さい。詳細は、PUTメソッドのサポート を参照下さい。

ファイルアップロード画面は、次のような特別なフォームを作成すること により、作成することができます。

例 19-1ファイルアップロード用のフォーム

<form enctype="multipart/form-data" action="_URL_" method="post">
<input type="hidden" name="MAX_FILE_SIZE" value="1000">
Send this file: <input name="userfile" type="file">
<input type="submit" value="Send File">
</form>
_URL_ はPHPファイルを指す必要があります。hidden フィールド MAX_FILE_SIZEは、input フィールド file の前に置く必要があります。 この値は、取得可能なファイルの最大サイズを規定します。この値はバイ ト数で指定します。

警告

MAX_FILE_SIZEはブラウザへの勧告に過ぎません。この最大値を 出し抜くのは簡単なことなので信頼してはいけません。しかし、 PHP側の最大サイズの設定を欺くことはできません。

ファイルのアップロードに際して定義さっる変数はPHPのバージョン及び 設定により異なります。以下の変数は、アップロードが行われた際に実行 されるスクリプト側で定義されます。 track_varsが有効な場合、 配列$HTTP_POST_FILES/$_FILESが初期化されます。 最後に、register_globalsが有効な場合 には、関連する変数がグローバル変数として定義することができます。 しかし、グローバル変数の使用はもはや推奨されていません。

注意 PHP 4.0.3以降、track_varsは 常にonです。PHP 4.1.0以降では、$_FILESを $HTTP_POST_FILESの代わりに使用することができま す。. $_FILES は常にグローバルです。このため、 $_FILESを関数スコープの中で使用する場合でも globalは不要です。

$HTTP_POST_FILES/$_FILESには、 アップロードされたファイルに関する情報が含まれています。

$_FILESの内容は次のようになります。ここでは、 上の例のスクリプトで使われたように、アップロードファイルの名前とし て'userfile'を使用することを仮定していることに注意して下さい。

$_FILES['userfile']['name']

クライアントマシンの元のファイル名。

$_FILES['userfile']['type']

ファイルのMIME型。ただし、ブラウザがこの情報を提供する場合。 例えば、"image/gif"のようになります。

$_FILES['userfile']['size']

アップロードされたファイルのバイト単位のサイズ。

$_FILES['userfile']['tmp_name']

アップロードされたファイルがサーバー上で保存されているテンポラ リファイルの名前。

注意 4.1.0より前のバージョンのPHPでは、この変数は $HTTP_POST_FILESで、自動グローバル(autoglobal) 変数ではありませんでした。PHP 3は、 $HTTP_POST_FILESをサポートしていません。

php.iniregister_globalsがonとなって いる場合、以下の変数が利用可能となります。 以下の変数名は、上の例で使用されているようにアップロードされたファ イルの名前として'userfile'を使用していることを仮定していることに注 意して下さい。

上記の変数のうち、"$userfile" は、アップロードフォームの type="file"を有する<input> フィールドのnameの値と関連すること に注意して下さい。上のアップロード用フォームの例においては、その値 を"userfile" としています。

注意 register_globals = Onは、セキュリティ及び性能 上の理由により推奨されません。

php.iniupload_tmp_dirディレクティブで 他の場所を指定しない限り、ファイルはサーバーにおけるデフォルトのテ ンポラリディレクトリに保存されます。サーバーのデフォルトディレクト リは、PHP を実行する環境において環境変数 TMPDIRを設 定することにより変更することができます。しかし、PHP スクリプトの内 部からputenv() 関数により設定しても上手くいきま せん。この環境変数は、アップロードされたファイルに他の処理を行う際 にも同様に使用することが可能です。

例 19-2ファイルのアップロードを検証する

以下の例は、4.0.2 より後のバージョンの PHP 4 用です。 is_uploaded_file() およびmove_uploaded_file()の関数のエントリを 参照下さい。

<?php 
// 4.1.0より前のPHPでは$FILESの代わりに$HTTP_POST_FILESを使用する必要
// があります。
if (is_uploaded_file($_FILES['userfile']['tmp_name'])) {
    copy($_FILES['userfile']['tmp_name'], "/place/to/put/uploaded/file");
} else {
    echo "ファイルアップロード攻撃をされた可能性があります。ファイル名: " . $_FILES['userfile']['name'];
}
/* ...または... */
move_uploaded_file($_FILES['userfile']['tmp_name'], "/place/to/put/uploaded/file");
?>

アップロードされたファイルを受け取る PHP スクリプトは、アップロー ドされたファイルを用いて何をするべきかを決めるために必要なロジック を全て実装する必要があります。例えば、変数 $_FILES['userfile']['size']を使用して、小さすぎ たり、大きすぎたりするファイルを捨てることができます。指定した型以 外のファイルを全て捨てるために変数 $_FILES['userfile']['type']を用いることができま す。何らかの方法により、テンポラリディレクトリからファイルを削除し たり、他の場所に移動したりする必要があります。

移動または名前の変更が行われていない場合、リクエストの終了時にその ファイルはテンポラリディレクトリから削除されます。