PHP脚本没有';下载大文件后无法完成

PHP脚本没有';下载大文件后无法完成,php,Php,我正在为一个网站开发一个PHP页面,该页面将文件压缩在一起,并允许用户下载。zip文件的大小可以从几MB到100MB不等。我的PHP脚本在临时目录中创建zip文件,然后将文件内容写入浏览器。完成后,脚本将更新MySQL数据库中的下载计数器,并从临时目录中删除zip文件 这一切都很好,直到我遇到一个大的zip下载,需要超过30秒max\u execution\u time设置为30,因此这是有意义的,但是如果我尝试使用set\u time\u limit(0)或更改max\u execution\

我正在为一个网站开发一个PHP页面,该页面将文件压缩在一起,并允许用户下载。zip文件的大小可以从几MB到100MB不等。我的PHP脚本在临时目录中创建zip文件,然后将文件内容写入浏览器。完成后,脚本将更新MySQL数据库中的下载计数器,并从临时目录中删除zip文件

这一切都很好,直到我遇到一个大的zip下载,需要超过30秒max\u execution\u time设置为30,因此这是有意义的,但是如果我尝试使用
set\u time\u limit(0)
或更改
max\u execution\u time
则会出现相同的结果。zip文件已从浏览器中成功下载,其中包含所有正确的文件,但脚本似乎随后停止,因为数据库未更新,服务器上的临时zip文件也未删除

这是一个包含Apache和PHP5.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 = "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的EasyHP。看来这可能和戈达迪有关

此外,在GoDaddy和本地站点上,我在脚本调用
set\u time\u limit
之前和之后打印了
max\u execution\u time
,结果分别为30和0,因此我不确定GoDaddy方面发生了什么

  • 可能是HTTP服务器配置中的问题?你在用什么?配置是什么
  • 另一种变体,当下载结束时,连接状态可能不等于0。因此,数据库更新条件下的代码根本不会被计算
  • php.ini中是否配置了日志记录错误?如果是,您是否查看了php.error.log,可能存在一些内存泄漏和“内存不足”错误

  • 仍然不确定为什么我上面使用的代码在托管站点上不起作用,但我找到了一个解决方法。如果我在live站点上使用PHP中的
    register\u shutdown\u函数
    调用,数据库将正确更新,文件将被删除

    以下是关机功能代码:

    <?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);
    }
    
    ?>
    
    
    
    您应该能够在php5.ini中设置最大执行时间,并使用PHP信息页面进行检查。您能否提供php5.ini的部分以及PHPinfo页面的输出?

    为什么不在磁盘中生成临时文件?为什么不让apache处理这些大的下载。php脚本可以响应300样式的链接,该链接可能超时。您的php是否在安全模式下运行?我不确定GoDaddy托管。好吧,基本上我在MySQL数据库中有一个事务ID,它告诉PHP将哪些文件拉到一起并放到zip下载中。我正在尝试跟踪数据库中事务的下载计数,然后让它删除文件。此外,安全模式似乎未启用。它是运行Apache的Linux环境中的GoDaddy帐户。我打开了错误日志,所以我将检查是否创建了任何日志。我已将php.ini中的error_log设置为有效文件名,但从未生成任何文件。GoDaddy具有错误记录功能,但不幸的是,它不适用于像我这样的经济型Linux帐户。我尝试将php5.ini中的max_execution_time更改为3600,并运行phpinfo(),输出显示为3600,但如果脚本每超过30秒,数据库和服务器文件将永远不会被删除,即使下载将在浏览器上完成。似乎使用寄存器功能关闭是更好的处理方法。