Zend Frameworkで大きなファイルをダウンロードする方法

このQ&Aのポイント
  • Zend Frameworkを使用して大きなファイルをダウンロードする方法を教えてください。
  • http://php.benscom.com/manual/ja/function.readfile.phpを参考に、Zend Frameworkでホームページのバックアップをtarファイル形式でダウンロードしたいと思っています。
  • 数Mbyte程度のファイルはダウンロードできましたが、大きなファイル(200Mbyte)ではエラーが発生しました。ファイルを途中で切れずにダウンロードする方法はありますか?
回答を見る
  • ベストアンサー

Zend Framework で大きなファイルをダウンロードしたい

ホームページをtarでバックアップしてZend Frameworkでダウンロードしたいのですが、 http://php.benscom.com/manual/ja/function.readfile.php を参考に次の様にしてみたところ、数Mbyte程度のファイルはダウンロードできましたが大きなファイル(200Mbyte)ではエラーになりました。 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(file_get_contents($file)); $response->outputBody(); } それで $response->setBody(file_get_contents(&$file)); $response->outputBody(); の部分を $handle = fopen($file, "rb"); $contents = ''; while (!feof($handle)) { $contents = fread($handle, 8192); $response->setBody($contents); $response->outputBody(); } fclose($handle); とかにしてみましたがこれもファイルが途中で切れてしまいました。 php.iniのメモリ量を増やす以外に、何か方法がありますでしょうか?

noname#207939
noname#207939
  • PHP
  • 回答数4
  • ありがとう数3

質問者が選んだベストアンサー

  • ベストアンサー
  • tany180sx
  • ベストアンサー率63% (239/379)
回答No.4

いちおZF-1.9.3にして試してみましたが同様で、 file_get_contents() => メモリサイズエラー fread() => 128MB保存(尻切れ) ob_end_clean() -> fread() => 170MB完全保存 となりました。 出力バッファリングのOFFは ob_end_clean() で可能です。 出力バッファリングが開始されていないと、このコールでエラーとなります。 ob_end_clean() は出力の前で呼んでますよね? 私のアドバイスはこの辺までかな...

noname#207939
質問者

お礼

最初から >出力バッファリングが制限をうけている気がします? とコメントをもらっていたのに、Zend Framework(上での出力バッファリング)を理解できていないようで、お手間を取らせてしまいました。たいへん申し訳ありません。 本当にありがとうございました。

noname#207939
質問者

補足

次のようにしたらダウンロードできました。 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; }

その他の回答 (3)

  • tany180sx
  • ベストアンサー率63% (239/379)
回答No.3

一応うちの環境では出力バッファリングOFFで最後まで出力できたのですが.. CentOS、PHP5.2.8、ZF1.9.? ソースは追ってないですがdispatchで出力バッファリングが開始されるのでは。 ResponseのoutputBodyはただechoするだけなので バッファリングが有効だと全部蓄えられていくことになります。 Framework通さずに同様の処理をさせると動作しますか?

noname#207939
質問者

補足

コメントありがとうございます。 次の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)
回答No.2

出力バッファリングが制限をうけている気がします? $response->sendHeaders(); ob_clean(); ob_end_clean();

noname#207939
質問者

補足

ob_clean(); ob_end_clean(); を入れてみましたがダメでした。これらはZend Frameworkを使わない場合では無いでしょうか?Zend Frameworkがresponseを管理しているので関係無いような気がします。どうすれば良いかはわかりませんが・・。

noname#94983
noname#94983
回答No.1

実際に同じ環境で試してないので想像でしかないが、これ、ひょっとしてサーバーとの接続がタイムアウトで切れている、ということはないだろうか? ブラウザを変えて試してみても同じだろうか。

noname#207939
質問者

補足

エラーは$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にどうやって渡すかという事かと思うのですが、わかりません。

関連するQ&A

  • ZendFrameworkでファイルDLできない

    ZendFrameworkでZIP圧縮したファイルをダウンロードさせようとしていますが、ファイルが正常に解凍できません。 「CRCが一致しないか、出力先が使用中です」とエラー表示されます。 一応、エラーが表示されても解凍はするのですが、ファイルを開こうとすると”ファイルが壊れています”と出てしまいます。 ちなみに、そのファイルをFTPでダウンロードし、通常に解凍すると正常に解凍されるので、ZendFramework上の何らかの処理が原因であると思われます。 また、症状の出ているのは数MB程度のデータで、サイズの小さい数百k程度のデータには起こっていないようです。 public function downloadAction(){ $file = abcde.zip; // ファイル名 $path = "/home/public/files/" . $file; // ファイルパス $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($path)); $response->sendHeaders(); $response->setBody(ob_end_clean()); $response->setBody(flush()); $response->outputBody(); $handle = fopen($path, "rb"); $contents = ''; while (!feof($handle)) { $contents = fread($handle, 8192); $response->setBody($contents); $response->outputBody(); } fclose($handle); return; } 何が原因だか教えて頂けないでしょうか。 宜しくお願いします。

    • 締切済み
    • PHP
  • PHP:wavファイルのダウンロード

    音楽ファイルを会員に配信するサイトを運営しています。 mp3は問題なくダウンロード・再生できるのですが、wavファイルはダウンロードしてもファイルが破壊されており、再生できません。 wavファイルのバイト数に変化はありませんでした。FTPからファイルをダウンロードすると正常に再生できるので、問題はウェブでのダウンロードをする過程にあることは分かっています。いろいろ調べているのですがそれ以降の原因が分からず困っています。 誰か原因をご存知の方、目星の付く方などおられましたら、ぜひ解答お願いいたします。 ファイルダウンロードには、以下のようなphp関数を使っています。 function download_file($path_file){ if (!file_exists($path_file)) { die("Error: No Such File."); } if (($content_length = filesize($path_file)) == 0) { die("Error: File size is 0.(".$path_file.")"); } if($_POST['sort'] == mp3){ header("Content-Type: audio/mpeg"); }elseif($_POST['sort'] == wav){ header("Content-Type: audio/x-wav"); } header("Content-Disposition: attachment; filename=\"" .basename($path_file)."\""); header("Content-Length: ".$content_length); header("Content-Transfer-Encoding: binary"); $handle = fopen($path_file, 'rb'); while (!feof($handle)) { echo fread($handle, 4096); ob_flush(); flush(); } fclose($handle); }

    • 締切済み
    • PHP
  • バイナリファイルをダウンロードできなくなりました。

    バイナリファイルをダウンロードできなくなりました。 以下のように、fopen で取得したバイナリデータをブラウザにダウンロードさせていましたが、ある時からダウンロードできなくなりました。 ・プログラムコードは変更していません。 ・同様の処理をしている全ての箇所が失敗するようになりました。 ・いずれも、かつては正常に動作していました。 ・ApacheやPHPはエラーメッセージを出力していません。 Apacheの設定またはPHPの設定を変えてしまったのかな、と推測していますが、原因がつかめていません。 検討がつかないので困っています。推測できる原因をご提示ください。 [環境] CentOS 5.3 (ルート権限も持っている、完全にコントロールできる環境です) PHP 5.1.6 Apache 2.2.3 [問題のコード その1] $ret=''; $handle = @fopen($file_name, 'r'); if ($handle) { while (!feof($handle)) $ret.=fread($handle, 8192); fclose($handle); } header('Content-disposition: attachment; filename="'.$src.'"'); header('Content-type: audio/3gpp'); header('Cache-Control: private'); header('x-jphone-copyright: no-transfer'); die($ret); [問題のコード その2] $url = "http://chart.apis.google.com/chart?".http_build_query($query); $img = @imagecreatefrompng($urls); $img = @imagerotate($img,270,0); header('Content-Type: image/jpeg'); imagejpeg($img); [問題のコード その3] $url = "http://example.net/example.php"; $options = array('http' => array( "method" => 'POST', "header" => "Content-Type: application/x-www-form-urlencoded\r\n" "content" => http_build_query($data), )); $contents = @file_get_contents($url, false, stream_context_create($options)); //書きだし header('Content-Type: application/x-shockwave-flash'); header('Content-Length: '.strlen($contents)); print $contents;

    • 締切済み
    • PHP
  • 外部ファイルの読み込み

    3つのファイルが同じディレクトリに入っているのですが、「main.php」を開くとphpがそのままテキストで表示されてしまいます。 phpを読み込んでhtml化した状態で表示するにはどうしたらいいでしょうか? test.txt ----------- テスト ----------- test.php ----------- <?PHP file_get_contents("test.txt"); ?> ----------- main.php ----------- <?PHP file_get_contents("test.php"); ?> ----------- main.phpを開くと ----------- <?PHP file_get_contents("test.txt"); ?> ----------- と表示されてしまいます。

    • ベストアンサー
    • PHP
  • PHPでバックアップ

    PHP初学者です、よろしくお願い致します。 PHPでバックアップを取りたく、次の様にしてみたのですが、実行するとファイルは正しいサイズでダウンロードされるのですが解凍すると中身は空になっています。できたファイルをFTPで別途ダウンロードして解凍してみると正常です。 $file = $storedir.$generatefile; $tstr = 'tar -C '.$upperdir. ' -czf '.$storedir.$generatefile.' '.$targetfolder; $result = system($tstr, $retval); if (file_exists($file)) { header('Content-Description: File Transfer'); header('Content-Type: application/octet-stream'); header('Content-Disposition: attachment; filename='.basename($file)); header('Content-Transfer-Encoding: binary'); header('Expires: 0'); header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); header('Pragma: public'); header('Content-Length: ' . filesize($file)); ob_clean(); flush(); readfile($file); } ファイルが出来上がっていないのにダウンロードが始まってしまうからでしょうか?もしそうならファイルが出来上がってからダウンロードが始まるようにするにはどうしたら良いでしょうか? 根本的にやり方が良くないようでしたらそれもご指摘いただければありがたいです。よろしくお願いいたします。

    • 締切済み
    • PHP
  • PHP zipファイルのダウンロード

    下記のようなPHPスクリプトにおいて、zip フォルダに画像ファイルの圧縮ファイルを 保存し、ダウンロードしたいんです。ダウンロードの動作はChrome上で確認できてますが、圧縮した、ダウンロードファイルのサイズが0KB で、空なのです。 どこが間違っているか教えていただけますか? [file_zip.php] <?php mb_internal_encoding("UTF-8"); $ftp = ftp_connect("~"); ftp_login($ftp, "~", "~"); $dir = '/storage2/zip'; ftp_chdir($ftp, $dir); // ディレクトリ移動 // Zipクラスロード $zip = new ZipArchive(); // Zipファイル名 $zipFileName = $_POST['zip_filename']; var_dump($zipFileName); // Zipファイル一時保存ディレクトリ $zipTmpDir = '/storage2/zip'; // Zipファイルオープン $result = $zip->open($zipTmpDir.$zipFileName, ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE); if ($result !== true) { // 失敗した時の処理 echo '圧縮ファイルをオープンできませんでした'; exit(); } // ここでDB等から画像イメージ配列を取ってくる $image_data_array = array(); array_unshift($image_data_array, $zipTmpDir.$zipFileName); // 処理制限時間を外す set_time_limit(0); foreach ($image_data_array as $filepath) { $filename = basename($filepath); // 取得ファイルをZipに追加していく $zip->addFromString($filename,file_get_contents($filepath)); } $zip->close(); // ストリームに出力 header('Content-Type: application/zip; name="' . $zipFileName . '"'); header('Content-Disposition: attachment; filename="' . $zipFileName . '"'); header('Content-Length: '.filesize($zipTmpDir.$zipFileName)); echo file_get_contents($zipTmpDir.$zipFileName); // 一時ファイルを削除しておく unlink($zipTmpDir.$zipFileName); // header("Location: storage.php"); ?>

    • 締切済み
    • PHP
  • PHPで定義されている関数のコードが見たい

    PHPでコードを記述するとき、関数を定義することがあります。 function test($name){ : : } しかし、最初から定義されている関数がありますよね。 isset()やfile_get_contents()などの関数です。 こういった関数の中身をみたいのですが、PHPのどの部分を見ればいいのでしょうか。 関数の中身とは、たとえばfile_get_contentsなら function file_get_contents($name){ : //この部分のことです。 : } PEARだったら、たとえばDB.phpならばDB,phpの中身を見ればいいのですが、fopen()などの最初から定義されている関数はどこを見れいいのかがわかりません。 よろしくお願いします。

    • ベストアンサー
    • PHP
  • PHPでのファイルのダウンロードについて

    お世話になります。 タイトルのとおりPHPでファイルのダウンロードを行いたいのですが、 ファイルを保存するというダイアログが出てくれません。 tesuto.php <?php $file="/work/tesuto.csv"; header ("Content-Disposition: attachment; filename=$file"); header ("Content-type: application/x-csv"); readfile ($file); ?> tesuto.phpを実行するとダウンロードされずに、ファイルの中身が表示されてしまいます。 よろしくお願いします。

    • ベストアンサー
    • PHP
  • function.fileに関してお尋ねします。

    サーバーへphpを使用した配布phpを設置したのですが、 phpのブラウザ上にfunction.fileと表示が出るためクリックすると、 403エラー ページが見つかりません。と表示されます。 確かめたのですがfunction.fileというようなものはダウンロードしたものに含めれておらず頭を傾げてるところです。 詳しい方が入ましたらご指導願いますでしょうか よろしくお願いします。 function.file-put-contentsではありませんので

    • ベストアンサー
    • PHP
  • サーバにあるエクセルファイルをダウンロード

    サーバ内にあるエクセルファイルをダウンロード画面からsubmitして、ダウンロードしたいのですが、ダウンロードしたファイルの内容が文字化けします。またなぜかダウンロード画面のhtml内容が張り付いてたりします。 XML形式で保存したエクセルファイルは問題なく保存→表示できるのですがどうしたらいいのか原因がわかりません。 ダウンロードのソースは、以下のようになっています。 <?php $out_path = mb_convert_encoding($file_path,"SJIS","UTF-8"); $out_file_name = basename($out_path); $file_size = filesize($out_path); header("Content-Type: application/vnd.ms-excel"); header("Content-Disposition: attachment; filename=\"" .     $out_file_name . "\""); header("Content-Length: ".$file_size); readfile($out_path); ?> ちなみに環境は以下のようになっています。 OS :XP 文字コード:UTF-8 framework :symfony 原因をご存知の方、ご教授よろしく御願いします。

    • 締切済み
    • PHP

専門家に質問してみよう