2012-04-12 7 views
4

データベースから.csvにデータをエクスポートしようとしています。エクスポートリンクをクリックすると、かなりの量のデータがあると、ブラウザに非常に長い時間保存ウィンドウが表示されません。スクリプトがしばらくぶら下がっていて、かなり長い時間が経ってブラウザにウィンドウを保存できるように見えるのであれば、かなり混乱するかもしれません。 コードは、コントローラにこのようなものです:データをエクスポートすると、ブラウザにブラウザが表示されないのはなぜですか

$this->_helper->layout->disableLayout(); 
     $this->_helper->viewRenderer->setNoRender(); 
     $fileName = $list->list_name . '.csv'; 

     $this->getResponse()->setHeader('Content-Type', 'text/csv; charset=utf-8') 
          ->setHeader('Content-Disposition', 'attachment; filename="'. $fileName . '"');  

     $contacts = new Contact(); 
     $contacts->export($listId); 

Exportメソッドは、レコードを一つずつ読み込み、それをこのような何か出力します:私はwinowはほとんどすぐに表示され、保存いくつかのアプリケーションに表示さ

$fp = fopen('php://output', 'w');   
    foreach ($mongodbCursor as $subscriber) { 
      $row = formRow($subscriber); 
     fputcsv($fp, $row); 
     }  

をし、保存をクリックすると、ダウンロードの進行状況が表示されます。

私は交換してみました:これで

$this->getResponse()->setHeader('Content-Type', 'text/csv; charset=utf-8') 
         ->setHeader('Content-Disposition', 'attachment; filename="'. $fileName . '"'); 

header('Content-Type: text/csv; charset=utf-8'); 
    header('Content-Disposition: attachment; filename="'. $fileName . '"'); 

それは、これまで助けにはなりませんでした。 データベースからすべてのデータが1つずつ読み込まれる前にヘッダーを送信することは可能でしょうか? ありがとうございます。

答えて

1

私はphp://出力に精通していません。私のアプリケーションは私の情報をfopen、fwrite、fcloseで一時ファイルに書き出します。オプション。

  $filesize = filesize("tmp/export.csv"); 
      header("Content-Type: text/csv"); 
      header("Content-Disposition: attachment; filename=\"export.csv\""); 
      header("Conent-Length: $filesize"); 
      readfile("tmp/export.csv"); 
      unlink("tmp/export.csv"); 
      exit; 

これは、ブラウザのダウンロードウィンドウをすぐに表示します。

+0

このようにエクスポートしたファイルの最大サイズはどれですか? – Oleg

+0

私は今あなたを理解していない、どのような輸入ですか?このコードは、同じスクリプトがその上に数行を書き込んだcvsを出力することです。最大ファイルサイズは無制限です(私のケースではデータベースエントリを読み込み、何千ものエントリを一度にエクスポートしても問題はありません)。 – peipst9lker

+0

Pardon、私はエクスポートを意味しました。 – Oleg

1

これを行うには、試みることができる:

    代わり $this->getResponse()->setHeader()(応答内容をバッファに保存し、それが完了したときにのみoutputedされる可能性があります - エクスポートが完了する時間)の
  • 呼び出しヘッダ機能
  • は、PHPに書き込むのではなく直接コンテンツをエコーし​​よう://出力(あなたがその前にヘッダを設定した場合、あなたはエコーすべてが生成されたCSVファイルに配置されます)

EDIT

関数は、配列として最初のパラメータを取得し",を追加し、コンテンツエコーprint_row

以下
function print_row($row) { 
     echo '"' . implode('","', $row) . '"' . "\r\n"; 
} 

ような機能をfputcsvを交換。

+0

交換方法を教えてください:\t \t $ fp = fopen( 'php://出力'、 'w'); \t \t \t fputcsv($ fp、$ row);直接エコーするのはどういう意味ですか?フィールド値、コマンド、改行を手動でエコーすることを意味しますか? – Oleg

+0

はい、私はあなたが '' value "、" value2 "\ r \ n'のようなものを各CSVラインに直接エコーすることができます。答えを編集し、使用できるサンプル関数を追加します。 –

+0

私は応答クラスのメソッドの代わりにヘッダ関数で置き換えようとしましたが、今は役に立ちませんでした。 – Oleg

0
// $file = path of 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'); 
header('Pragma: public'); 
header('Content-Length: ' . filesize($file)); 
ob_clean(); 
flush(); 
readfile($file); 
exit; 

出典:http://php.net/manual/en/function.readfile.php

+0

あなたのアイデアと私のコードに何が間違っているか説明してください。 – Oleg

+0

私のアイデアはファイルリンクからダウンロードする必要があり、コードに何が問題なのかはわかりません。 – MakuraYami

+0

私の質問には答えられないようです。 – Oleg

0

あなたContent-Type値のapplication/force-downloadの代わりtext/csvを使用してみてください。

header("Content-Type: application/force-download; name=\"" . $fileName . "\""); 

この

はちょうどブラウザでコンテンツ を示すのではなく、実際のダウンロードボックスを強制します。典型的には、ダウンロードをトリガするためにPHPコードと組み合わせて使用​​され、

マイムアプリケーション/力ダウンロード、典型的にはMIMEアプリケーション/ X-力ダウンロードのように表される:ここ

MIME ApplicationからいくつかのドキュメントでありますWebブラウザでコンテンツを表示するのではなく、

たとえば、Webブラウザで表示するのではなく、ダウンロードしたいファイルがWebサイトにある場合は、ファイルのヘッダーコンテンツタイプフィールドに適切なMIMEアプリケーション/強制ダウンロードコードを入力します。 mime application/force-downloadは登録されたMIMEタイプではありません。さらに、PHPコードで使用する場合、mime application/force-downloadの推奨スペルには「x-」という接頭辞が含まれています。

+0

ヘッダーは次のように使用しますか?header( 'Content-Type:application/force-download; charset = utf-8'); \t \t \t \t \t header( 'Content-Disposition:attachment; filename = "'。$ fileName。 '"'); – Oleg

+0

問題は、ヘッダーがデータベースからデータを取得した後にのみ送信され、この間にヘッダーがクライアントに送信されないということです。だからかなり長い間送られてきたわけではないので、何らかのヘッダーに問題があるとは思えません。それは多くの問題を引き起こす可能性のある標準的なMIMEではありません。 – Oleg

+0

上記のヘッダーを使用しようとしましたが、それは助けに見えません。 – Oleg

0

私はこれが良い解決策であるかどうか分かりませんが、それほど多くは探っていませんでしたが、うまくいくようです。 エクスポートする前にヘッダの後ろにバッファにいくつかのデータを追加した後で、それが可能になります。

header('Content-Type: text/csv; charset=utf-8'); 
    header('Content-Disposition: attachment; filename="'. $fileName . '"'); 

    echo str_pad('', ini_get('output_buffering'));  
    ob_flush(); 
    flush(); 

    Model_Subscriber1::exportList($listId); 

それは私がZendのbootstrap.phpの中に追加のコントローラで動作するようにするには:

/** 
* hint to the dispatcher that it should not use output buffering to capture output generated by action controllers. 
* By default, the dispatcher captures any output and appends it to the response object body content. 
*/ 
protected function _initFront() 
{ 
    $frontController = Zend_Controller_Front::getInstance(); 
    $frontController->setParam('disableOutputBuffering', 1);   
} 

この場合には、私はすぐにブラウザにダウンロードウィンドウを取得し、データがかなり取ることができた輸出しているみたいに見えます長い間。この解決策が現在受け入れ可能かどうかはわかりません。私はそれについてあなたの意見をここで喜んでいるだろう。 エクスポートファイルに空のデータを追加する際に問題が発生します。 だから、コントローラーを変更します。このような何かへの輸出のための

header('Content-Type: text/csv; charset=utf-8'); 
    header('Content-Disposition: attachment; filename="'. $fileName . '"'); 

    Model_Subscriber1::exportList($listId); 

そしてチャン機能:

foreach ($mongodbCursor as $subscriber) { 
      $row = formRow($subscriber); 
    echo '"' . implode('","', $row) . '"' . "\r\n"; 
    ob_flush(); 
    flush();      

    }  
0

あなたの機能は、フラッシュ/ ob_flush直前長い操作を呼び出すと、HTTPヘッダーが長いプロセスの前にクライアントに送信できるようにするとよいでしょう。