0

私は、ファイルを一緒に圧縮してユーザーがダウンロードできるようにするWebサイトのPHPページに取り組んでいます。zipのファイルサイズは、数MBから100MBの範囲です。私のPHPスクリプトは、一時ディレクトリにzipファイルを作成してから、ファイルの内容をブラウザに書き込みます。これが完了すると、スクリプトはMySQLデータベースのダウンロードカウンターを更新し、tempディレクトリからzipファイルを削除します。

30秒以上かかる大きなzipダウンロードに出くわすまで、これはすべて正常に機能します。 max_execution_timephp.iniファイルでは30に設定されているため、これは理にかなっていますが、使用set_time_limit(0)または変更しようとするmax_execution_timeと、同じ結果が発生します。zipファイルは、すべての正しいファイルが含まれている状態でブラウザーから正常にダウンロードされますが、データベースが更新されておらず、サーバー上の一時zipファイルが削除されていないため、スクリプトは後で停止するようです。

これは、ApacheとPHP5.2を備えたLinux環境です。

このWebサイトは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 = "0123456789abcdefghijklmnopqrstuvwxyz";

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);

?>

更新:ローカルWebサーバーから別のダウンロードを実行しようとしましたがusleep、ダウンロード時間を遅くするためにコマンドを10000に上げました。合計ダウンロード時間は1分強かかり、データベースが更新され、ファイルが/tmpから削除されます。私のローカル環境では、Windows7ボックスでApacheとPHP5.3を使用してEasyPHPを実行しています。これはGoDaddyと関係があるようです。

また、GoDaddyとローカルサイトの両方で、スクリプトから呼び出されるmax_execution_time前後に印刷しましset_time_limitたが、結果はそれぞれ30と0でした。そのため、GoDaddy側で何が起こっているのかわかりません。

4

3 に答える 3

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);
}

?>
于 2012-05-01T17:02:26.077 に答える
0
  1. たぶんあなたのHTTPサーバーの設定に問題がありますか?何を使用していて、構成は何ですか?
  2. 別の変形として、ダウンロードが終了すると、接続ステータスが0に等しくない場合があります。そのため、データベース更新の条件にあるコードはまったく評価されません。
  3. php.iniで設定されたエラーログはありますか?はいの場合、php.error.logを調べましたか?メモリリークと「メモリ不足」エラーが発生している可能性があります。
于 2012-04-30T21:11:07.443 に答える
0

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

于 2012-05-01T21:54:29.783 に答える