質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Apache

Apacheは、Apache HTTP Serverの略で、最も人気の高いWebサーバソフトウェアの一つです。安定性が高いオープンソースソフトウェアとして商用サイトから自宅サーバまで、多くのプラットフォーム向けに開発・配布されています。サーバーソフトウェアの不具合(NCSA httpd)を修正するパッチ(a patch)を集積、一つ独立したソフトウェアとして開発されました。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

解決済

3回答

10465閲覧

PHPでファイルをダウンロードさせる際のブラウザ側タイムアウトについて

mosa

総合スコア218

Apache

Apacheは、Apache HTTP Serverの略で、最も人気の高いWebサーバソフトウェアの一つです。安定性が高いオープンソースソフトウェアとして商用サイトから自宅サーバまで、多くのプラットフォーム向けに開発・配布されています。サーバーソフトウェアの不具合(NCSA httpd)を修正するパッチ(a patch)を集積、一つ独立したソフトウェアとして開発されました。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

0グッド

0クリップ

投稿2017/04/20 03:33

編集2017/04/20 04:23

いつも本当に助かっています。

PHPのプログラムでファイルをダウンロードさせる際のブラウザ側タイムアウトについての質問です。
今までは、サーバサイドで大規模なCSVを生成し順次レスポンスストリームに流すことでCSVファイルをダウンロードさせていました。
非常に時間がかかる処理ですが、レスポンスストリームにデータが流れ続けているためかタイムアウトにはなりませんでした。
それを「サーバサイドでZIPファイル化し、それをダウンロードさせる方式」にしたところ、CSVファイル生成→ZIP化が完了するまで一切レスポンスがなくなるため、ブラウザ側でタイムアウト(Chromeでは30分)するようになりました。
非同期にすれば解決するのはわかるのですが、できるだけ現状を維持したいため、なるべく簡単な方法を探しています。
そんなに時間のかかる処理はいかがなものか、そんなに大規模なCSVをどうするんだ、という問題もあるかと思いますが、その辺は今回は無視してください。

プログラムのイメージは以下のとおりです。

PHP

1ini_set('max_execution_time', 7200); 2set_time_limit(0); 3 4// ZIPファイル生成のとても時間がかかる処理 5 6header('Content-Type: application/zip;'); 7header('Content-Disposition: attachment;filename="huge.zip"'); 8$file = fopen($zip, 'r'); 9while(!feof($file)) echo fread($file, 8192); 10fclose($file);

Apache2.4
PHP5.6 (CakePHP3.2)


ブラウザ側のタイムアウト(Chrome)

イメージ説明

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

長い処理中に定期的にレスポンスを返してやれば(進捗表示のように)いいかなと思いましたが、それだと最後にファイルを送ることができませんね。
ファイルを送るのではなくリンクを表示させてダウンロードは別途やらせるのがよいのでしょうかね。(そのリンク自体も直接ではなくすれば、ダウンロード後に削除とかもできそうです)

※参照先を記入したメールを送る、とかいろいろ手はありそうですが

投稿2017/04/20 04:58

tacsheaven

総合スコア13703

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mosa

2017/04/20 05:06

ありがとうございます。 そうなんですよね・・・。何かを返せば回避できると思うのですが、返してしまうとZIPファイルが壊れてしまうので・・・。 後付ですみませんが、今回はロードバランシングしたサーバのローカルにZIPファイルを生成しているため、別途ダウンロードにしてしまうと、色々面倒が多いもので、横着しようとかんがえてしましたが、やはり1リクエストで完結させるのはでは不可能そうですね。
guest

0

ob_flush() するとかどうでしょう。

【PHPでプログレス表示を行うには? - エンブリッジ・プロジェクトマネジャーブログ | エンブリッジ株式会社】
https://www.enbridge.jp/blog/2007/08/17232951.php

投稿2017/04/20 04:45

kei344

総合スコア69400

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mosa

2017/04/20 05:08

ありがとうございます。 頂いた情報を元にこちらで検証中ですが、今回はファイルダウンロードなので、何かを返却してしまうとzipファイルが壊れてしまうので、何も返却せずにob_flash()を試してみようと思います。
mosa

2017/04/20 06:13

やってみましたがダメでした。やはり何も返却せずにob_flash()ではダメなようでした。
kei344

2017/04/20 06:20

zipの最初部分( fread($file, 8192); で最初に返す部分)を1バイトごと返して行くとか無理でしょうか・・・。ファイルのヘッダ部分はある程度固定のバイナリが並んでいそうな気がするですが、ばらばらですかね。
mosa

2017/04/20 06:23

fread() に処理が行くまでの処理が長く、それの前にタイムアウトしてしまいます。
mosa

2017/04/20 06:25

あ、すみません。勘違いしました。ZIPファイルのバイナリヘッダ部分はおそらくどれも同じだから、ゆっくりそれを返却し、その間に処理をしてみる、ということですね。 興味深い方法ですが、難しそうですね。やり方が私には・・・。
guest

0

ファイルが出来上がるまでに時間がかかるのであれば
予約制にしてファイルをプールする方式にすればよいでしょう。
一度ダウンロードしたファイルはダウンロード後に削除するか
一定期間が経過した後削除するようにすればよいかと
(もちろん明示的な削除を指示した時のみでもOK)

投稿2017/04/20 03:51

yambejp

総合スコア114784

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mosa

2017/04/20 03:55

ありがとうございます。 非同期であればできるのはわかるのですが、今回はロードバランシングされたサーバでローカルにファイルを生成しているため、できれば同一リクエスト内で処理したいと思っています。 ですが、簡単な方法がなければ、非同期にしようかと思います。
yambejp

2017/04/20 04:10

あくまでタイムアウトが発生するようなケースを想定しての話なので もちろん待てるのであれば待つという選択肢もあるでしょう むしろ待てないという前提の質問ではないのでしょうか?
mosa

2017/04/20 04:26

言葉足らずですみません。 ユーザは待てる想定ですが、ブラウザがタイムアウト(Chromeなら30分)してしまうのでそれを回避する方法はありますか、という質問です。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問