PHP下载zip存档大文件大小

时间:2012-07-18 07:39:06

标签: php

日冰,

我有一个带有多个复选框的表单,允许用户在提示下载zip文件之前选择他们想要的小册子。 zip存档下载功能正常运行。但我意识到下载会话将在不下载整个文件(例如8MB)的情况下终止,下载的zip文件将被破坏。

参考下面的代码,它没有解决问题。任何人都可以建议我需要调查的设置是什么,或者我错过了任何功能?

if($send) {     
    // Make sure program execution doesn't time out
    // Set maximum script execution time in seconds (0 means no limit)
    set_time_limit(0);

    $post = $_POST;     
    $file_folder = "pdf/";  // folder to load files
    $zip = new ZipArchive();    // Load zip library 
    $zip_name = "File-".time().".zip";          // Zip name
    if($zip->open($zip_name, ZIPARCHIVE::CREATE)!==TRUE){       // Opening zip file to load files
        $error .=  "* Sorry ZIP creation failed at this time<br/>";
    }
    foreach($post['brochure'] as $file){                
        $zip->addFile($file_folder.$file);          // Adding files into zip
    }
    $zip->close();
    if(file_exists($zip_name)){
        // set headers push to download the zip
        header("Pragma: public");
        header("Expires: 0");
        header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
        header("Cache-Control: public");
        header('Content-type: application/zip');
        header("Content-Transfer-Encoding: Binary");
        header('Content-Disposition: attachment; filename="'.$zip_name.'"');
        header("Content-Length: ".filesize($zip_name)); 
        readfile($zip_name);
        // remove zip file is exists in temp path
        unlink($zip_name);

        $fp = @fopen($zip_name, "rb");
        if ($fp) {
         while(!feof($fp)) {
             print(fread($fp, 1024*8));
             flush(); // this is essential for large downloads
             if (connection_status()!=0) {
                 @fclose($file);
                 die();
             }
         }
         @fclose($file);
        }
    }

3 个答案:

答案 0 :(得分:1)

而不是制作“readfile()”你尝试过这种解决方案吗?

if(file_exists($zip_name)){
    header("Pragma: public");
    header("Expires: 0");
    header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
    header("Cache-Control: public");
    header('Content-type: application/zip');
    header("Content-Transfer-Encoding: Binary");
    header('Content-Disposition: attachment; filename="'.$zip_name.'"');
    header("Content-Length: ".filesize($zip_name)); 

    echo file_get_contents($file);
    exit
}

对我而言,它更简单,它在很多时候对我很好。

在此之后,我看到的问题是你做了:

unlink($zip_name);
$fp = @fopen($zip_name, "rb");
if ($fp) {
    ...
}

这部分代码永远不会继续,因为你在打开它之前取消链接文件!

答案 1 :(得分:0)

首先,您的if ($fp) {...}块永远不会被执行,因为您之前已经完成了unlink($zip_name);。所以这个区块没用。

中学,我建议您替换

readfile($zip_name);

ob_clean();
flush();
readfile($zip_name);

这样可以防止意外的边框效果。

最后,如果您仍然存在损坏的存档(我相信),那么我认为这是因为在下载刷新之前,期间或之后发生了一些PHP错误(请注意您的PHP代码似乎没有在下载后结束,因此代码可能会继续,并且可能会发生一些错误)。如果发生了这样的PHP错误或PHP通知,则已使用流输出PHP错误消息。这很容易检查:使用文本编辑器打开损坏的存档以查看二进制内容,然后PHP错误消息应该在存档的二进制内容的开头或最底部显得清晰可读。无需在HEXA模式下打开存档。

答案 2 :(得分:0)

使用以下代码管理以解决我的问题。基本上我不应该在调用fopen之前取消链接文件。

if($send) {
    // Make sure program execution doesn't time out
    // Set maximum script execution time in seconds (0 means no limit)
    set_time_limit(0);

    $post = $_POST;     
    $file_folder = "pdf/";  // folder to load files
    $zip = new ZipArchive();    // Load zip library 
    $zip_name = "File-".time().".zip";          // Zip name
    if($zip->open($zip_name, ZIPARCHIVE::CREATE)!==TRUE){       // Opening zip file to load files
        $error .=  "* Sorry ZIP creation failed at this time<br/>";
    }
    foreach($post['brochure'] as $file){                
        $zip->addFile($file_folder.$file);          // Adding files into zip
    }
    $zip->close();
    if(file_exists($zip_name)){

        // set headers push to download the zip
        header("Pragma: public");
        header("Expires: 0");
        header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
        header("Cache-Control: public");
        header('Content-type: application/zip');
        header("Content-Transfer-Encoding: Binary");
        header('Content-Disposition: attachment; filename="'.$zip_name.'"');
        header("Content-Length: ".filesize($zip_name)); 

        //readfile($zip_name);
        // remove zip file is exists in temp path
        //unlink($zip_name);

        $fp = @fopen($zip_name, "rb");
        if ($fp) {
         while(!feof($fp)) {
             echo fread($fp, 8192);
             flush(); // this is essential for large downloads
             if (connection_status()!=0) {
                 @fclose($zip_name);
                 die();
             }
         }
         @fclose($zip_name);
        }
        unlink($zip_name);
    }
}