PHPでCSV出力。ダウンロードせず文字化けしてブラウザで表示される。

久しぶりにCSV出力を実装したときの覚書。

環境: nginx 1.20.1, PHP 7.4.6

CSVでダウンロードするように実装した後、データが多くなると文字化けしてダウンロードまでいかない現象が発生。

参考サイト

ポイントは

  • fputcsv前にheader関数を使いHTTPヘッダーを送信(設定)する。
    参考: PHP: header - Manual
  • output_bufferingを十分な値に設定する。
    参考: PHP: 実行時設定 - Manual
  • 【追記】output_bufferingを使わずにtempnamで一時ファイルを生成してダウンロードするべき。
    参考: PHP: tempnam - Manual


output_bufferingの詳細

output_bufferingは出力するための作業領域容量を設定する。

生成するCSVファイルが大きくなる可能性がある場合は、実ファイルとして保存する処理に変更する。

そもそも出力バッファを使わずに実ファイルとして生成→readfile→unlinkするべき。
ファイル名は他の処理と被らないようにランダム生成。

tempnamという関数を使うと簡単に実装可能。
参考: PHP: tempnam - Manual

どうしても出力バッファを使いたい場合はoutput_bufferingの設定を変更する。
# less /etc/php.ini

output_buffering = 40960

再読み込み
# systemctl reload php-fpm

ちなみにPHP CLIは常にoutput_bufferingが0なのでコマンドで確認しても常に0。
# php -i | grep output

ブラウザでphpinfo()を確認する必要がある。