- ベストアンサー
phpでダウンロード処理に失敗する事があります
- phpにてexcelを作成後にダウンロードさせる処理を作成したのですが、excelのサイズが100MBを超える様な時にダウンロードが失敗する事があります。ブラウザは転送速度0のまま待っている状態でエラーは出ていない状態です。
- phpのエラーログやapacheのログにも何の情報も表示されていません。スクリプトにconnection_abortedやconnection_statusで接続が切れた場合にエラーログを吐く様に試しましたが何も出力されていませんでした。
- 使用している環境はCentOS Linux release 7.7.1908、Apache/2.4.6、PHP 5.6.40で、ブラウザはChromeの最新版を使用しています。
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
うーん、他の点というと、今気になったのが >$tmpfile = "hogehoge.xlsx"; こちらは実際もそのままでしょうか? 現在時刻あるいはユーザー名等をファイル名に取り込んで、バッティングしない工夫とかされていれば良いんですが。 もし固定ファイル名だと、誰かがダウンロード中に別の誰かがこのスクリプトを起動して、転送中のファイルを更新してしまう事故があるかもしれないと思いました。
その他の回答 (2)
- asciiz
- ベストアンサー率70% (6809/9681)
flush() の仕様かなとか考えてたんですが、気になる記述がありました。 >https://so-zou.jp/web-app/tech/programming/php/sample/progress.htm こちらに >スクリプトが実行可能な時間は制限されており、この時間を超えると >スクリプトは強制的に終了させられます。この時間は既定で30秒であり、 >長時間の処理を実行するには注意が必要です。 >制限時間を超えたときには、 >Fatal error: Maximum execution time of 30 seconds exceeded in C:\index.php on line 10 >のようなエラーが表示されます。 ということでして。 >この制限はset_time_limit()によって、実行可能な秒数を設定することで >回避できます。なお、ゼロ秒とすると時間の制限はなくなります。 >PHP: set_time_limit - Manual >https://www.php.net/manual/ja/function.set-time-limit.php ということなので、ファイル送信開始する前に set_time_limit(120); とか set_time_limit(max(30, intdiv($size, 500000))); (30秒または500KB/sで計算した秒数で転送できなければタイムアウト) みたいにすればいいでしょうかね? ※ダウンロード速度は受け手側の環境にも左右されます。ADSLの4Mbps当たりが最低かなと考えて、4Mbps=500KB/sという値を使ってみました さすがに set_time_limit(0); とはやらない方がいいと思います。走ったままのプロセスがいくつも積みあがってメモリ不足になる危険性がある気が。 ---- あれ? 頭に >ini_set("set_time_limit",0); がありますが…これは… >phpのini_set("max_execution_time",n)とset_time_limitの違いについて調べた >http://kannokanno.hatenablog.com/entry/2017/05/27/220521 実は ini_set("max_execution_time",0); の間違いだったという凡ミスでしょうか。 まあでも私としては0セットはお勧めできないので、set_time_limit() でファイルサイズに応じたタイムアウトを設定した方が良いと思います。
お礼
回答ありがとうございます。 ご指摘頂いた max_execution_time に対して テスト的に 0 をセットし実行してみましたがダウンロード出来たりできなかったりの状態です。エラーログに何も出力されないので何処から疑ってよいのやらです。何か他に疑うべき個所等、お知恵を貸していただければ幸いです。
- OKWave_77777
- ベストアンサー率8% (7/87)
そのとおり よくあります
お礼
phpでの改善は難しいと思いxsendfileでの処理を試しましたがphpと同じ挙動を見せたためhttpd.confを見直しSendBufferSizeの設定をデフォルトに戻したところ問題無くダウンロード出来る様になりました。
補足
回答ありがとうございます。 ファイル名ですが、質問するにあたり簡略化しておりました。実際には str_shuffle("abcdefghijklmnopqrstuvwxyz") . ".xlsx" として重複を防いでおります。情報を小出しにするような形となり申し訳ありませんでした。又、この処理にアクセスしているのは今のところ私だけで複数のリクエストは来ていない状態です。