2012-04-30 23 views
0

ファイルをまとめてダウンロードできるWebサイトのPHPページを作成しています。 zipのファイルサイズは、数MBから100MBの範囲であればどこでもかまいません。私のPHPスクリプトはzipファイルを一時ディレクトリに作成し、ファイルの内容をブラウザに書き出します。これが完了すると、スクリプトはMySQLデータベースのダウンロードカウンタを更新し、一時ディレクトリからzipファイルを削除します。大容量ファイルのダウンロード後にPHPスクリプトが終了しない

これは、30秒以上かかる大規模なzipダウンロードが発生するまで、すべて正常に動作します。 php.iniファイル内のmax_execution_timeは30に設定されていますが、これは意味がありますが、set_time_limit(0)を使用するか、max_execution_timeを使用しても同じ結果が得られます。 zipファイルはブラウザから正常にダウンロードされますが、データベースは更新されず、サーバー上の一時的なzipファイルは削除されないため、スクリプトは後で停止するようです。

これはApacheとPHP 5.2のLinux環境です。

このウェブサイトはGoDaddyでホストされていますので、スクリプトで実行できる時間制限の変更に制限があるのか​​どうかはわかりませんが、基本的には完了するまで無期限に実行します。

制限時間や回避策を設定できない理由についてのご意見はありますか?

は、ここに私のコードです:

<?php 

// Don't stop the script if the user 
// closes the browser 
ignore_user_abort(true); 
set_time_limit(0); 

// Generate random name for ZIP file 
$zip_file = ""; 
$characters = "abcdefghijklmnopqrstuvwxyz"; 

do 
{ 
    $zip_file = "tmp/"; 

    for ($p = 0; $p < 10; $p++) 
     $zip_file .= $characters[mt_rand(0, strlen($characters))]; 

    $zip_file .= ".zip"; 
} while (file_exists($zip_file)); 

// Prepare ZIP file 
$zip = new ZipArchive(); 

/* Open and add files to ZIP (this part works fine) 
. 
. 
. 
*/ 

// Close and save ZIP 
$zip->close(); 

// Check browser connection 
if (connection_status() == 0) 
{ 
    // Send ZIP 
    header("Content-Type: application/zip"); 
    header("Content-Length: " . filesize($zip_file)); 
    header("Content-Disposition: attachment; filename=Download.zip"); 
    header("Cache-Control: no-store, no-cache, must-revalidate"); 
    header("Cache-Control: post-check=0, pre-check=0", false); 
    header("Pragma: no-cache"); 
    header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); 
    header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); 

    // Save and then delete file 
    //readfile($zip_file); 
    if ($file = fopen($zip_file, "r")) 
    { 
     // Set buffer size 
     $buffer_size = 1024 * 8; 

     // While we're still transmitting 
     // send over bytes! 
     while(!feof($file) && (connection_status() == 0)) 
     { 
      print(fread($file, $buffer_size)); 
      flush(); 
      usleep(10000); //<!-- Download speed cap 
     } 

     // Close file descriptor 
     fclose($file); 
    } 
} 

/* Update database download counter if connection_status() == 0 
. 
. 
. 
*/ 

// Delete the file 
unlink($zip_file); 

?> 

UPDATE:私はちょうど私のローカルWebサーバーから別のダウンロードをやってみましたし、ダウンロード時間を遅くするために10000にusleepコマンドを格上げ。ダウンロード時間の合計が1分を少し超えてデータベースが更新され、ファイルが/ tmpから削除されました。私のローカル環境では、Windows 7のボックスでApacheとPHP 5.3を使ってEasyPHPを実行します。これはGoDaddyと関係があるようだ。

max_execution_timeまた、set_time_limitがスクリプトから呼び出された後、結果がそれぞれ30と0になったので、GoDaddy側で何が起こっているのか分かりません。

+0

なぜディスクに一時ファイルを生成しないのですか? –

+0

なぜあなたはApacheの大規模なダウンロードを扱わないのですか? PHPスクリプトは、タイムアウトする可能性のあるリンクに300のスタイルに対応することができます。 –

+0

PHPは安全モードで動作していますか? GoDaddyのホスティングについてはわかりません。 –

答えて

0

私が上記のコードを使用している理由は、ホスティングサイトでは機能しませんが、回避策が見つかりました。ライブサイトでregister_shutdown_functionコールをPHPで使用すると、データベースが正しく更新され、ファイルが削除されます。

ここシャットダウン機能コードです:

<?php 

$filesize = 0; 
$total_bytes_read = 0; 
$download_query = ""; 
$zip_file = "tmp/download.zip"; 

register_shutdown_function("shutdown"); 

/* Other code for creating ZIP file and reading it out to the browser 
. 
. 
. 
*/ 

function shutdown() 
{ 
    global $filesize; 
    global $total_bytes_read; 
    global $zip_file; 
    global $download_query; 

    // Update the database if file was fully downloaded 
    if ($filesize != 0 && $filesize == $total_bytes_read) 
    { 
     /* Do database update with $download_query 
     . 
     . 
     . 
     */ 
    } 

    // Delete the file 
    unlink($zip_file); 
} 

?> 
0
  1. HTTPサーバーの設定に問題がありますか?あなたは何を使っていて、何が設定されていますか?
  2. 別の変形では、ダウンロードが終了すると、接続ステータスが0にならないことがあります。したがって、データベースの更新条件のコードはまったく評価されません。
  3. php.iniにエラーログが設定されていますか?はいの場合、php.error.logを調べました。多少のメモリリークや「メモリ不足」エラーがあります。
+0

Apacheを実行しているLinux環境のGoDaddyアカウントです。私はエラーログを有効にしたので、ログが作成されているかどうか確認します。 – Zac

+0

php.iniのerror_logを有効なファイル名に設定しましたが、ファイルは生成されません。 GoDaddyにはエラーログ機能がありますが、残念ながら私のような経済的なLinuxアカウントでは機能しません。 – Zac

0

はあなたのphp5.iniであなたのmax_execution_timeに設定し、PHPの情報ページでこれをチェックすることができるはずです。あなたはphp5.iniのセクションとPHPinfoページからの出力を提供できますか?

+0

php5.iniのmax_execution_timeを3600に変更してphpinfo()を実行してみましたが、出力に3600が表示されましたが、スクリプトが30秒以上かかると、ブラウザでダウンロードが完了してもデータベースとサーバーファイルは削除されません。これは、register_function_shutdownを使用する方が良い方法です。 – Zac

関連する問題