忍者ブログ

STEP UP BLOG

Home > ブログ > > [PR] Home > ブログ > php > readfile()での巨大ファイルの出力

readfile()での巨大ファイルの出力

むかーしむかし、あるところにおじいさんとおばあさんが住んでいました。
おじいさんは山へ芝刈りに、おばあさんは川へ洗濯に行きました。
おばあさんが川で洗濯をしていると、どんぶらこ、どんぶらこ、と大きなCSVファイルが流れてきました。
それはそれは大きく見事なCSVファイルだったので、おばあさんはダウンロードしようとしました。
しかし、ダウンロードしようとしたらブラウザが真っ白になってしまいました。
おやおや、困ったものだとおばあさんは途方に暮れました。
・・・・・・


というわけで巨大なファイルをダウンロード出来なかったという話です。
あらかじめ大きなファイルだということは認識していたので、
サーバ側PHPのファイル出力にはreadfile()を用いています。

http://php.net/manual/ja/function.readfile.php
注意: readfile() 自体にはメモリに関する問題はなく、 巨大なファイルを送ってもかまいません。out of memoryエラーが出る場合は、 ob_get_level() で出力バッファリングを無効にしてください。

マニュアルの注意書きにも、巨大なファイルを送ってもかまわないと書いてあります。
しかし、実際はエラー。
エラーログを確認するとメモリーのエラーです。
おやおや、とマニュアルの注意書きの"out of memoryエラーが出る場合は、 ob_get_level() で出力バッファリングを無効にしてください。"がなんだか怪しそうです。
試しにソースコードのファイル出力部分でob_get_level()を実行してみると、2と出ました。

http://php.net/manual/ja/function.ob-get-level.php
返り値 ¶ 出力バッファリングハンドラのネストレベルを返します。 バッファリングがアクティブでない場合はゼロを返します。

によると、この関数は出力バッファリングのネストレベルを返し、無効の場合は0を返すとのこと。
ということは、readfile()で巨大なファイルを出力するためにはob_get_level()が0でないといけない。
出力バッファリングを無効にするためにはob_end_clean()を実行すればよいとのことで、
実行してob_get_level()で確認したら0になるわけではなく2から1減ってネストレベルが1になっただけ。
デクリメントかい。
ob_get_level()が0になるまでob_end_clean()を実行します。
while (ob_get_clean()) {
    ob_end_clean();
}

このようにして出力バッファリングを無効にした後にreadfile()することで、
やっと巨大ファイルのダウンロードに成功しました。
めでたしめでたし。
PR

Comment0 Comment

Comment Form

  • お名前name
  • タイトルtitle
  • メールアドレスmail address
  • URLurl
  • コメントcomment
  • パスワードpassword

PAGE TOP