2012-09-13 58 views
1

僅供參考,我已經閱讀並試圖在這些問題的答案,其他幾個線程:PHP下載腳本創建不可讀的ZIP文件在Mac

Creating and serving zipped files with php

Opening downloaded zip file creates cpgz file?

我有一個zip文件上我的服務器。

  1. 當我使用FileZilla中從我的服務器Zip文件移動到我的Mac,我可以正常打開。

  2. 當我使用此PHP代碼將Zip文件下載到我的Linux機器時,它正常打開。

  3. 當我使用此PHP代碼將Zip文件下載到我的Mac,使用Safari或Firefox時,出現「Decompression Failed」或「The archive of the archive is damaged」錯誤,或者我得到.cpgz文件 - 我相信這意味着計算機正在壓縮文件,而不是解壓縮文件。

這裏是我使用提供zip文件中的PHP代碼。

$zipname = "myfile.zip"; 
$zippath = "/path/to/" . $zipname; 

     if ($downloadzip = fopen ($zippath, "r")) { 
      $fsize = filesize($zippath); 

      header("Content-type: application/zip"); 
      header("Content-Disposition: attachment; filename=\"".$zipname."\""); 
      header("Content-length: $fsize"); 
      header('Content-Transfer-Encoding: binary'); 
      #header("Cache-control: private"); //use this to open files directly 

      echo fpassthru($downloadzip); // deliver the zip file 

     } 
     fclose ($downloadzip); 

我發現了一些工作的標題。我真的不知道或不在乎它爲什麼工作,我只是很高興它的工作原理...我嘗試了很多不同的東西,.htaccess文件,php.ini/zlib設置。

這裏的答案 http://perishablepress.com/http-headers-file-downloads/

$zipName = 'myfile.zip'; 
$zipPath = 'mydirectory/' . $zipName; 


    if (file_exists($zipPath)) { 

     header("Pragma: public"); 
     header("Expires: 0"); 
     header("Cache-Control: must-revalidate, post-check=0, pre-check=0"); 
     header("Cache-Control: public"); 
     header("Content-Description: File Transfer"); 
     header("Content-type: application/octet-stream"); 
     header("Content-Disposition: attachment; filename=\"".$zipName."\""); 
     header("Content-Transfer-Encoding: binary"); 
     header("Content-Length: ".filesize($zipPath)); 
     ob_end_flush(); 
     @readfile($zipPath); 
} 
+0

當您更換'回聲fpassthru($ downloadzip)會發生什麼'?你試過刪除:'header('Content-Transfer-Encoding:binary');'? –

+0

當我使用'readfile()'時,它以0.2 MB的方式進入,這是小的方式。我已經刪除了'header('Content-Transfer-Encoding:binary');'但沒有區別。 – Chris

回答

4

這裏是什麼工作

$zipName = 'myfile.zip'; 
$zipPath = 'mydirectory/' . $zipName; 

    if (file_exists($zipPath)) { 

     header("Pragma: public"); 
     header("Expires: 0"); 
     header("Cache-Control: must-revalidate, post-check=0, pre-check=0"); 
     header("Cache-Control: public"); 
     header("Content-Description: File Transfer"); 
     header("Content-type: application/octet-stream"); 
     header("Content-Disposition: attachment; filename=\"".$zipName."\""); 
     header("Content-Transfer-Encoding: binary"); 
     header("Content-Length: ".filesize($zipPath)); 
     ob_end_flush(); 
     @readfile($zipPath); 
} 
+0

花費了幾個小時尋找這個謝謝你... –

0

好吧,我想你知道你的$ FSIZE變量沒有被寫入到頭部,因爲它是由引號括起來。 你可以嘗試這樣的事:

header('Cache-Control: public'); 
header('Content-Description: File Transfer'); 
header('Content-Disposition: attachment; filename=\"".$zipname."\"'); 
header('Content-Type: application/zip'); 
+0

$ fsize應該可以正常工作,它被雙引號包圍,而不是單引號。 –

+0

我確實認爲$ fsize正在工作,當我註釋掉該標題行時,下載並不知道該文件有多大。當該標題行正在使用時,下載確實知道該文件有多大。 – Chris

+0

@Chris我的錯誤。嘗試將大小添加到我給出的上述標題,然後查看是否有效。 – chriscct7

5

通常情況下,問題是由已打印或回顯到頁面多餘的字符導致你讀出前文件。即使是空間也會導致失敗。要解決該問題,請在讀取將清除輸出緩衝區並關閉緩衝的文件之前調用ob_end_clean();

但是要記住,你可以有嵌套輸出緩衝器,這將破壞你的下載,以及(歡呼Vladamir爲搞清楚了這一點)。因此,要清除輸出緩衝區完全運行這個你讀文件之前:

while (ob_get_level()) { 
    ob_end_clean(); 
}  

這將清除出你的整個緩衝區,你不會有任何額外的字符來弄亂你的下載。

對於那些有興趣我已經粘貼我的下載腳本下面。我的zip文件現在可以完美下載,到目前爲止,這很好。通過`ReadFile的(zippath $)`;

if (file_exists($zip_file_path)) { 

     header("Pragma: public"); 
     header("Expires: 0"); 
     header("Cache-Control: must-revalidate, post-check=0, pre-check=0"); 
     header("Cache-Control: public"); 
     header("Content-Description: File Transfer"); 
     //We can likely use the 'application/zip' type, but the octet-stream 'catch all' works just fine. 
     header("Content-type: application/octet-stream"); 
     header("Content-Disposition: attachment; filename='$zip_file_name'"); 
     header("Content-Transfer-Encoding: binary"); 
     header("Content-Length: ".filesize($zip_file_path)); 

     while (ob_get_level()) { 
      ob_end_clean(); 
     } 

     @readfile($zip_file_path); 

     exit; 
} 
+0

經過幾小時你的週期解決了我的問題。清理每個緩衝區是解決方案。 –

+1

很高興我能幫到你。它直到我在另一個網站上找到這個解決方案時,也把我扔了一圈。快樂的編碼... – Maximus

+0

我一直努力工作數小時。感謝十億Maximus!我從來沒有想過,ob_get_level循環將完成這項工作!謝謝!!!! – InspiredCoder