- ベストアンサー
Zend Frameworkで大きなファイルをダウンロードする方法
- Zend Frameworkを使用して大きなファイルをダウンロードする方法を教えてください。
- http://php.benscom.com/manual/ja/function.readfile.phpを参考に、Zend Frameworkでホームページのバックアップをtarファイル形式でダウンロードしたいと思っています。
- 数Mbyte程度のファイルはダウンロードできましたが、大きなファイル(200Mbyte)ではエラーが発生しました。ファイルを途中で切れずにダウンロードする方法はありますか?
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
いちおZF-1.9.3にして試してみましたが同様で、 file_get_contents() => メモリサイズエラー fread() => 128MB保存(尻切れ) ob_end_clean() -> fread() => 170MB完全保存 となりました。 出力バッファリングのOFFは ob_end_clean() で可能です。 出力バッファリングが開始されていないと、このコールでエラーとなります。 ob_end_clean() は出力の前で呼んでますよね? 私のアドバイスはこの辺までかな...
その他の回答 (3)
- tany180sx
- ベストアンサー率63% (239/379)
一応うちの環境では出力バッファリングOFFで最後まで出力できたのですが.. CentOS、PHP5.2.8、ZF1.9.? ソースは追ってないですがdispatchで出力バッファリングが開始されるのでは。 ResponseのoutputBodyはただechoするだけなので バッファリングが有効だと全部蓄えられていくことになります。 Framework通さずに同様の処理をさせると動作しますか?
補足
コメントありがとうございます。 次の2つでテストしています。 (ローカル)WindwosXP, Apache 2.2.11, PHP Version 5.2.9-2, Zend_Version=1.9.2 php.ini : memory_limit = 128M, output_buffering = Off (レンタルサーバー)sixcore, OS Linux , Apache 2.2.3 , PHP 5.1.6 , Zend_Version=1.9.2 php.ini : memory_limit = 30M, output_buffering = 4096 Frameworkを通さない場合として http://php.benscom.com/manual/ja/function.readfile.php の「例1」は、どちらも200Mbyteのファイルを保存できました。 Frameworkの中に「例1」を置いた場合ですが、index.phpやControllerファイルの中の function init() に置いた場合は200byteのファイルを同様に保存できました。 Actionの中に置くとエラーになります。 $contents = fread($handle, 8192);にした場合はファイルが途中で切れてしまったと書きましたが、ローカルでは約120Mbyteで途切れたファイルが作られ、レンタルサーバーでは約30Mbyteで途切れたファイルが作られます。 FrameworkのバッファリングをOFF(?)にできるのでしょうか?
- tany180sx
- ベストアンサー率63% (239/379)
出力バッファリングが制限をうけている気がします? $response->sendHeaders(); ob_clean(); ob_end_clean();
補足
ob_clean(); ob_end_clean(); を入れてみましたがダメでした。これらはZend Frameworkを使わない場合では無いでしょうか?Zend Frameworkがresponseを管理しているので関係無いような気がします。どうすれば良いかはわかりませんが・・。
実際に同じ環境で試してないので想像でしかないが、これ、ひょっとしてサーバーとの接続がタイムアウトで切れている、ということはないだろうか? ブラウザを変えて試してみても同じだろうか。
補足
エラーは$response->setBody(file_get_contents(&$file));の場合は Fatal error: Allowed memory size of 31457280 bytes exhausted (tried to allocate 183808001 bytes) で、$contents = fread($handle, 8192);の場合は Internal Server Error になります。IEでもFirefoxでも同じです。 ですのでタイムアウトではなく大きなファイルをresponseにどうやって渡すかという事かと思うのですが、わかりません。
お礼
最初から >出力バッファリングが制限をうけている気がします? とコメントをもらっていたのに、Zend Framework(上での出力バッファリング)を理解できていないようで、お手間を取らせてしまいました。たいへん申し訳ありません。 本当にありがとうございました。
補足
次のようにしたらダウンロードできました。 public function DownloadAction(){ $file = "test.bin"; $this->_helper->viewRenderer->setNoRender(); $response = $this->getResponse(); $response->clearAllHeaders(); $response->clearBody(); $response->setRawHeader('Content-Description: File Transfer'); $response->setRawHeader('Content-Type: application/octet-stream'); $response->setRawHeader('Content-Disposition: attachment; filename='.basename($file)); $response->setRawHeader('Content-Transfer-Encoding: binary'); $response->setRawHeader('Expires: 0'); $response->setRawHeader('Cache-Control: must-revalidate, post-check=0, pre-check=0'); $response->setRawHeader('Pragma: public'); $response->setRawHeader('Content-Length: ' . filesize($file)); $response->sendHeaders(); $response->setBody(ob_end_clean()); $response->setBody(flush()); $response->outputBody(); $handle = fopen($file, "rb"); $contents = ''; while (!feof($handle)) { $contents = fread($handle, 8192); $response->setBody($contents); $response->outputBody(); } fclose($handle); return; }