HHeLiBeXの日記 正道編

日々の記憶の記録とメモ‥

PHPでのファイルアップロードの処理

ファイルアップロードのファイルサイズチェック - Qiitaを読んでて非常にもやっとしたので、PHPプログラム側のエラー処理を自分なりに整理してみたメモ。

ちなみに検証環境は訳あって以下だが、CentOS 7でも同様だと思う。

php.iniの設定は以下のようになっている。

;;;;;;;;;;;;;;;;;
; Data Handling ;
;;;;;;;;;;;;;;;;;

; Maximum size of POST data that PHP will accept.
; http://www.php.net/manual/en/ini.core.php#ini.post-max-size
post_max_size = 8M

;;;;;;;;;;;;;;;;
; File Uploads ;
;;;;;;;;;;;;;;;;

; Maximum allowed size for uploaded files.
; http://www.php.net/manual/en/ini.core.php#ini.upload-max-filesize
upload_max_filesize = 2M

送信側のHTMLおよび受信側のPHPプログラムをベタで書き起こすと以下のような感じになるだろう。

  • ファイル送信側のHTML
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <title>$_FILES test</title>
    </head>
    <body>
        <h1>[php.iniのupload_max_filesize] &gt; [hiddenのMAX_FILE_SIZE]</h1>
        <form action="upload.php" method="post" enctype="multipart/form-data">
            <input type="hidden" name="MAX_FILE_SIZE" value="1048576" />
            <input type="file" name="file1" />
            <input type="submit" value="アップロード1" />
        </form>
        <h1>[php.iniのupload_max_filesize] &lt; [hiddenのMAX_FILE_SIZE]</h1>
        <form action="upload.php" method="post" enctype="multipart/form-data">
            <input type="hidden" name="MAX_FILE_SIZE" value="3145728" />
            <input type="file" name="file1" />
            <input type="submit" value="アップロード2" />
        </form>
    </body>
</html>
  • 受信側のPHPプログラム
<a href="./">Back to Home</a>
<hr />
<pre>
<?php
var_dump($_POST);
var_dump($_FILES);
?>
</pre>
<hr />
<?php
$param = 'file1';
if (isset($_FILES[$param])) {
    $err = $_FILES[$param]['error'];
    if ($err === UPLOAD_ERR_OK) {
        if (is_uploaded_file($_FILES[$param]['tmp_name'])) {
            print('OK。何の問題もありません。');
        } else {
            print('えっ!?何が起きた?');
        }
    } else if ($err === UPLOAD_ERR_INI_SIZE) {
        print('ファイルサイズが大きすぎます(php.iniのupload_max_filesize)。' . ini_get('upload_max_filesize') . 'バイト以下にしてください。');
    } else if ($err === UPLOAD_ERR_FORM_SIZE) {
        print('ファイルサイズが大きすぎます(formのMAX_FILE_SIZE)。' . $_POST['MAX_FILE_SIZE'] . 'バイト以下にしてください。');
    } else if ($err === UPLOAD_ERR_PARTIAL) {
        // XXX アップロード中にキャンセルした場合とか?
        print('「アップロードされたファイルは一部のみしかアップロードされていません。」');
    } else if ($err === UPLOAD_ERR_NO_FILE) {
        print('「ファイルはアップロードされませんでした。」');
    } else if ($err === UPLOAD_ERR_NO_TMP_DIR) {
        // XXX upload_tmp_dirで設定したディレクトリが存在しない場合かと思ったが、
        // 「ここで指定したディレクトリに書き込むことができない場合、 PHP はかわりにシステムのデフォルトテンポラリディレクトリを使用します。」らしい。
        print('「テンポラリフォルダがありません。」');
    } else if ($err === UPLOAD_ERR_CANT_WRITE) {
        // XXX ディスク容量不足の場合とか?
        print('「ディスクへの書き込みに失敗しました。」');
    } else if ($err === UPLOAD_ERR_EXTENSION) {
        print('「PHP の拡張モジュールがファイルのアップロードを中止しました。」');
    }
} else {
    // post_max_sizeを超えている
    print('ファイルサイズがあまりに大きすぎます。' . ini_get('upload_max_filesize') . 'バイト以下にしてください。');
}

とまぁ、結構めんどくさいことになるので、必要なエラーコードだけ拾ってきちんと処理し、残りは適当にあしらうのが良いのかなと。「UPLOAD_ERR_NO_TMP_DIR」とかなんか完全にサーバー側の設定の問題だしな。

参考