PHPでダウンロード処理を作る
あまり問題になることが多いわけではありませんが、PHPの場合、普通に出力しているだけだと、HTMLページ以外を出力する場合に問題が発生する場合があります。
特に、ダウンロード系だと顕著にそれが出る場合があります。
具体的にはどんなこと?
まず起こりうるものとしては、CSVで出したくて、Content-Dispositionにちゃんとファイル名を入れているにもかかわらず、ファイルの最後に.htmlがくっついて出てきてしまう場合。
もう一つは特にバイナリ系のダウンロード (WordやExcel形式)で起きやすいのですが、開くと普通に開けるのに、正しくないと警告が出る場合。
の2つが主になります。
それはなぜ?
これの起こる原因としてPHPの出力バッファという機構が関係しています。
よく、不正なテキストが不正なタイミングで出力されないようにob_startという関数を使う場合があるかと思います。
しかし、このob_start、PHPのあるバージョンからデフォルトで何重にも張られています。
ためしにob_get_levelを実行して取得した値を見ると分かりますが、だいたい3〜5くらいの値が何もしなくても返ってきます。
すなわち、PHPが何か余計なものをバッファに溜め込んでいる場合がある、ということです。
それが余計なデータとなって、先ほどのような不具合の原因となります。
回避するには?
言語としてはセーフティネットの役割もあるんでしょうけど、システムとしては邪魔なだけですのでおとなしく消えてもらいたいと思います。
具体的にどうするかというと、
while (ob_get_level() > 0) {
ob_end_clean();
}
のようなコードを適当な場所に突っ込むだけです。
そのあとで、システムとしてob_startを一回呼び出せば、邪魔なデータはすべて消えてしまい、希望したデータを出力することができるようになります。