2012-07-18 92 views
1

嗨,Php下载zip档案大档案大小

我有一个窗体有多个复选框,它允许用户选择他们想要的小册子,然后提示他们下载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); 
     } 
    } 

回答

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) { 
    ... 
} 

的这部分代码不应该继续下去,因为你打开它之前,断开链接的文件!

+0

嗨文森特,谢谢你的回复。我面临的问题是下载会话总是在几秒钟后终止而不下载整个zip文件。 – Xoozlez 2012-07-18 08:41:43

+0

它对我的解决方案做了同样的事情? 如果下载是在它结束之前被截断的,我不认为它是一个PHP的问题:( – PoulsQ 2012-07-18 20:37:39

0

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

次,我建议你用

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

这种替代

readfile($zip_name); 

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

+0

Hihi Skrol,我已经根据你的建议替换了编码。但是我面对的问题是下载会话总是终止几秒钟后(下载的文件是est 2.5mb)而不下载整个zip文件(8mb) – Xoozlez 2012-07-18 08:44:18

+0

Hi Xoozlez,如果会话终止,你应该在zip二进制文件中有一个PHP通知,除非你避免了错误报告。如果您已经避免了错误报告,我建议您将它们打开以便能够阅读可能的错误。不过,使用'set_time_limit()'来延长会话时间。 – Skrol29 2012-07-18 09:19:41

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