http://php.net/manual/ja/features.file-upload.post-method.php
<input type="file" /> で指定したファイルは、リクエストのボディ部に MIME の multipart という形式で格納されてサーバに送信されます。
http://www.atmarkit.co.jp/ait/articles/0104/18/news002.html
# 上記はメールの添付ファイルについて書かれていますが、<input type="file" /> で送信するときも同じです。
バイナリのファイルは BASE64 という形式でテキスト化されます。
BASE64 でエンコードされたデータは、大体 4割くらい元のデータよりもサイズが大きくなります。
http://ja.wikipedia.org/wiki/Base64
PHP の最新は 5.6.6 でしょうか。
ダウンロードページから、ソースを落として読んでみました。
http://php.net/downloads.php
BASE64 のデコード、つまりリクエストで送られた MIME の multipart 形式で格納されたデータを境界で切り分けて、ここのファイルをバイナリに戻す時に呼び出される関数(のはず)です。
php-5.6.6/ext/standard/base64.c
/* {{{ proto string base64_decode(string str[, bool strict]) Decodes string using MIME base64 algorithm */ PHP_FUNCTION(base64_decode) { char *str; unsigned char *result; zend_bool strict = 0; int str_len, ret_length; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &str, &str_len, &strict) == FAILURE) { return; } result = php_base64_decode_ex((unsigned char*)str, str_len, &ret_length, strict); if (result != NULL) { RETVAL_STRINGL((char*)result, ret_length, 0); } else { RETURN_FALSE; } } /* }}} */
パラメータ領域からデータを切り出して、str が指す領域に格納し、php_base64_decode_ex という関数でデコード(バイナリに戻す)したデータのアドレスを戻します。
少なくとも、リクエストパラメータはメモリ領域にすべて展開されること、BASE64 でエンコードされたパラメータが保持されたままで、ひとつのファイルはデコードされる、ということが分かります。
つまり、1Mbyte のファイルを 5つ送った場合には、
の、計 8Mbyte は 少なくともメモリ上に確保されます。
# MIME multipart の境界やヘッダ、その他のリクエストパラメータは、誤差の範囲
アップロードされたファイルの実体は $_FILES['userfile']['tmp_name'] でアクセスされるということは、一旦、テンポラリの領域に実データとして保存されているということなので、送信した全てのファイルがデコードされた状態でメモリに展開されるわけではなく、ひとつのファイルをデコードしてテンポラリ領域に保存する、というふうに処理されていると思います。