• ベストアンサー

先にダウンロードダイアログを表示させる方法

お世話になります。 ブラウザから「データ取得」なんてボタンを押すと、データベースからデータを取得して、結果をcsvとして出力するプログラムを考えています。 ただ、データがかなり大きいため、データを取得してくる間の待ち時間が結構あります。この間にブラウザを操作されたりするのも問題なので、ブラウザ側からはすぐに「ダウンロードダイアログ」が出せないでしょうか? あわよくば、ダウンロードしてる、みたいなフリの最中に計算処理とかできるかな?なんて考えたのですが… header("Content-Type: application/octet-stream"); header("Content-Disposition: attachment; filename=$file.csv"); ~データ取得処理~ print $受け取ったデータ; こんなのでどうかなと思いましたが、ダメでした。何か良い方法ありませんでしょうか。よろしくお願いいたします。

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

  • ベストアンサー
  • wp_
  • ベストアンサー率54% (132/242)
回答No.5

オフトピですが、 >HTMLの仕様に httpっす^^; // 当方もこれは最初混同してましたねぇ・・・ >FireFox2=意図通りの動作! >IE6=やっぱり全てのデータが揃うまで待つ 突っ込みを入れますと、 通信速度が生成速度を超えるとファイルが尻切れになる気がします。^^; 単純ロジックなら問題ないでしょうけども。 ちなみにこの二つで差異が発生するのはhttp云々関係なく、ただのブラウザの実装の違いだったりします。 なので「どっちが正しい」と言うのはあまりなかったり。(UI的にはIEが礼儀正しい。) >ajax やるならばこれが一番現実的ですが、No.4の方が言うとおり手間と時間の割りに得られる恩恵と達成感がないかもしれません。^^; 生成するサーバと生成完了の応答を行うサーバが同一だった場合はインフラ周りに一工夫必要でしょうし、 何よりデバッグが大変です。 当方的にはボタン押下で別ページに遷移させ、locationヘッダで自動遷移させ落とすファイルへアクセスさせたいですね。 // 窓の杜とかそうなっていたと記憶、「ダイアログが出ない場合はこちら」のリンクがあったと思います。 こうするとユーザもボタンを謳歌したということを知ることができ、何度もボタンを押される事故が減ります。

tom7net
質問者

お礼

失礼いたしました、不勉強なもので色々混同してしまってます。 >突っ込みを入れますと、 >通信速度が生成速度を超えるとファイルが尻切れになる気がします。^^; >単純ロジックなら問題ないでしょうけども。 数回テストした環境でたまたま動いただけかもしれませんし、この場合はアテにならなそうですね。 >ajax おっしゃる通り、仕組みそのものを検討する必要があるようですので、自分一人の問題だけではすまなそうです。 主題自体は、「こういう方法ないのかな?」くらいの考えでしたが、様々な意見をいただいた上で見ますと、動作自体を考え直す方がよさそうですね。勉強になりました。 いただいた意見を参考に検討しなおしてみます。 ありがとうございました。

その他の回答 (4)

  • 64bit
  • ベストアンサー率51% (45/88)
回答No.4

以前似たようなことをやろうとして、仕様策定までやって、面倒なのでやめた者です。 Ajaxを使えばおそらく出来ます。 1) クリックしたときに「ダウンロードダイアログっぽいもの」をJavaScriptで手動で出力する 2) サーバでは出力を計算しながら少しずつ一時ファイルに書き込んでいく 3) クライアントでは、1秒程度おきにサーバに「処理が終わったか?」を問い合わせるリクエストを非同期で出す 4) 終わっていなければ「処理中・・・」と表示 5) 終わったら、一時ファイルにリダイレクトする 6) 一時ファイルは、一定時間後に削除するようCRONか何かで設定する これは、処理に時間がかかってブラウザが諦めてしまうのを防ぐために考えたものですが、結局作っていませんので、うまく動くかは分かりません。 30秒以上かかるプロセスでも無いと、手間に見合わないかもしれません・・・

tom7net
質問者

お礼

ありがとうございます。 確かに希望の動作になりそうですが、Ajaxを組み込むことを考えますと、仕組みそのものを検討しなおさなければいけませんね… PHPだけでちょいちょい、というわけにはいかなそうですね。動作など色々検討してみます。

  • yambejp
  • ベストアンサー率51% (3827/7415)
回答No.3

なんかデータをおくらないとはじまらないですね。 header("Content-Type: application/octet-stream"); header("Content-Disposition: attachment; filename=$file.csv"); print "\n"; flush(); ~データ取得処理~ print $受け取ったデータ; なんでもいいので一発おくってflushしてからその後の処理をしてみては?

tom7net
質問者

お礼

ありがとうございます。 アドバイス内容のテストを行ってみました。ちょっとブラウザ間で差が出ました。 FireFox2=意図通りの動作! IE6=やっぱり全てのデータが揃うまで待つ という結果でした。 ANo.2.wp_さんのお話通りですと、FF2が仕様に沿ってないのかもしれません。もう少しいじってみます。

  • wp_
  • ベストアンサー率54% (132/242)
回答No.2

落とされる可能性があるファイルを日次バッチなどで舐めてあらかじめファイルを作っておくとか。 動的に生成しなければならない場合やデータの種類が膨大な場合はこの手法を使えませんけども。 主題の「ダウンロードダイアログを先に出しておいてデータだけ生成」というのはhttpの仕様上不可能です。 サーバは「送信するコンテンツを確定してからクライアントに送信」します。 データ長などの検査の都合上、これは避けられない(はず)です。 データを生成しながらコンテンツをクライアントに送信する仕組み、いわゆるストリームのようなことをしたいのであれば httpでなく、そのようなことが出来るプロトコル・サーバを使うしかありません。

tom7net
質問者

お礼

ありがとうございます。 今回のデータは動的に生成しないとダメなので、事前に作っておくというのは無理です。 簡単な方法があるんじゃないかと考えていましたが、HTMLの仕様に触れてしまっているとなると、ちょっと難しそうですね…

  • yambejp
  • ベストアンサー率51% (3827/7415)
回答No.1

>こんなのでどうかなと思いましたが、ダメでした やり方自体はもんだいないと思いますがどうだめなのでしょうか?

tom7net
質問者

お礼

すいません、説明が足りませんでした。 やりたいこと: ブラウザから取得ボタンを押せば、待ち時間を置かずに「ダウンロードしますか?」というダイアログが出て欲しい。 現状: IE6とFirefox2でテストしただけですが、どうもCSVのデータが全部揃うのを待ってから「ダウンロードしますか?」のダイアログが表示されてくるようで、大変待ち時間が多いです。