PHPでのファイルアップロードの最大値の設定

PHPのファイルアップロードについてです。
ファイルアップロードの最大値は、 php.ini で決める事になります。


グーグル先生にお伺いをたてると、よく、

memory_limit >= post_max_size >= upload_max_filesize

といった、関係式が出てきます。


memory_limit は PHPが使用できるメモリの最大値です。スクリプトが暴走してメモリを食いつぶすのを防いでくれたりします。

post_max_size は POSTを使って、クライアント(ブラウザ)から送ることが可能な最大のデータ量です。

upload_max_filesize はPOSTで送られてくるデータのうち、ファイルとして送られてくるデータの最大値となります。


さて、上の関係式ですが、「PHP 5.2.6」でシステム構築をしていた時に気づいたのですが、間違いです。そうとしか思えません。
もしくは、4.x系でのお約束だったのかもしれません。


まず、memory_limit は、32MBにしても、16MBにしても、それ以上のサイズのファイルをアップロードすることが可能でした。
よくある説明で「ファイルはメモリに保存されるので・・・」とかありますが、php.ini の upload_tmp_dir で指定したディレクトリに一時保存されます。指定していない場合、UNIXでは /tmp に保存されます。
なので、アップロードの最大容量には関係ないようです。
てか、1GBとか2GBのファイルをアップロードするのに、そのサイズのメモリ(物理か論理かは置いといて)を要求されたら、使い物にならないです。
# アップロードデータ受信時の読み取りキャッシュに使われるかもしれないので、まったくの無関係ではないかもしれません。そこは未調査。


次に、post_max_size ですが、ファイルアップロードではPOSTメソッドを使用するため、この値がアップロードするファイルサイズより小さいとアップロードされませんでした。

<?php var_dump($_FILES); ?>

というスクリプトにファイルを送りつけると、空の配列が表示されたので、POSTデータのサイズ以上はそもそも無視されるようです。
非常に大きいデータでは接続を切断されました。


最後に、upload_max_filesize についてです。
これは「1セッションでアップロード可能なファイルサイズ」です。
これは、どうやら「複数のクライアントから同時にアップロードされているファイルの合計サイズ」のようです。

てっきり、1セッションあたりのアップロードサイズだと思っていたのですが、開発でベンチマークをとる際に、
upload_max_filesize=900MBを指定している状態で、500MBぐらいのファイルを2つ同時にアップロードしてみたところ、
あとからファイルをアップロードしたセッションが切断されました。別々のPCからアップロードを試して見ましたが同様の結果でした。

例えば、200MB を指定していて、1人あたり 50M のファイルをアップロードする場合、同時に4人までしかアップロードできないことになります。


結局、ファイルのアップロードサイズの変更には、upload_max_filesize と post_max_size を適切に設定しれやればいいようです。
しかし、upload_max_filesize の指定は、同時利用の事まで考えて設定する必要があるようなのでちょっと大変です。
とりあえず、POSTの最大サイズと同じではダメみたいです。1ユーザに食いつぶされる可能性がありますので。

# ふと、APCの影響でこういうことになってるのでは・・・と思ったり・・・。 あとで実験します。


ちなみに、ファイルアップロードの進捗状況を取得したい場合は、APCを使うと実現できます・・・が、それはまたの機会に。

追記 2008.06.05 12:00

upload_max_filesizeの話。
テスト用に作ったC#のプログラムだと制限にひっかかる感じだけど、Firefoxで送るとそんなことはないようです。
再調査中・・・。

追記 2008.06.05 15:15

上の話、ブラウザからはうまく動作するので、C#のHttpWebRequestが原因のようです。。。
なぜか複数セッションはってるように見えてない様な感じ。
調査中。