- ベストアンサー
大容量CSVファイルをダウンロードするには
お世話になります。 PHPを使ってOracleのデータをCSV化しようとしています。 データサイズが400MBくらいなので簡単に、 Maximum execution time of *** seconds exceeded とか Allowed memory size of **** bytes exhausted になってしまいます。 途中で分割して送る方法があれば、 教えていただきたいと思います。 よろしくお願いします。
- みんなの回答 (2)
- 専門家の回答
質問者が選んだベストアンサー
header("Content-Type: application/octet-stream") header("Content-Disposition: attachment; filename=$csv_file"); echo [CSVの1行目にDBのカラム名] ----ループの始まり [DBから取り出し] [DBから取り出したデータの編集] echo [DBから取り出して編集したカンマ区切りデータ] ----ループの終わり としたらいいんじゃないでしょうか
その他の回答 (1)
- t_ohta
- ベストアンサー率38% (5253/13739)
Maximum execution time ・・・ に対しては set_time_limit(0); とかすればスクリプト実行のタイムアウトを防げます。 Allowed memory size ・・・ に対しては、Oracleから一度にデータ全件を取り出さずに、少し取り出して出力、続きを少し取り出して出力といった感じで徐々に処理するようにすればメモリの消費を抑えられます。 もしくは、予めCSVファイルを作っておいて、それをダウンロードさせるという方法も検討してはいかがでしょうか。
補足
Oracleから少しずつ取り出すところまでは出来ているので、 あとは、 DBアクセス ->ダウンロード DBアクセス ->ダウンロード ・ ・ ・ という分割イメージを実現できれば良いのですが、 途中でユーザにダウンロードさせる、 というのをどうやるのかがよくわかりません。 それが質問のきっかけになったのですが、 現在は、テーブルの一定行の単位にループを回しており、 DBアクセス毎にheaderを書いて、 取得したデータをechoしてます。 ----ループの始まり header("Content-Type: application/octet-stream") header("Content-Disposition: attachment; filename=$csv_file"); $myData = CSVの1行目にDBのカラム名 $myData .= DBから取り出して編集したカンマ区切りデータ echo $myData; ----ループの終わり これだと、最後に作ったCSVしかダウンロードできず、しかもカラム名がループ回数分続くだけでした。 よろしくお願いします。
お礼
本当に助かりました。 ありがとうございます。
補足
実行してみました。 1回目のループでダウンロードを開始した後、 2回目以降が連続してダウンロードされます。 DBアクセス ->ダウンロード DBアクセス ->ダウンロード ・ ・ のような分割イメージにはなりませんでしたが、 逆に、ユーザが途中に介在しないので、 こちらのほうが理想的です。 しかも、 Maximum execution time of *** seconds exceeded とか Allowed memory size of **** bytes exhausted が出なくなり、元々の悩みが解決しました。