試著產生 ZIP 壓縮檔,下載檔案產生後,解壓縮時卻顯示「這個壓縮檔不是未知的格式就是損壞。」
研究了一下,原因是因為我用到了 TemplatePower,在頁首就 include 了 TemplatePower,使得頁面輸出壓縮檔時有了多餘的字元。
為了讓檔案順利下載,可以將使用者導到另一頁去取得下載檔案,也可以調整目前頁面。我的做法就是調整一下使用 TemplatePower 的時機。(原本把 include class.TemplatePower.inc.php 的語句寫在第一行,把它往後移,以確保執行下載作業時不會引入這一行)
修正這個問題後仍然無法正確解壓縮,發現壓縮檔裡的每個檔案檔名都是亂碼。
這個的修正就是透過 mb_convert_encoding() 函式來轉換檔名編碼。因為我存在資料庫的檔名是 UTF-8,但檔案系統只想讀 big5,所以把編碼轉換後,就沒事了。(同事提醒我,不要用 iconv() 這種過時的危險轉碼)
程式碼大致如下。
<?php
if($isOK){
// 使用者點選下載按鈕,進行下載作業
getDownloadFile();
}
else{
require_oncedirname(__FILE__).'/templatepower/class.TemplatePower.inc.php';// 引用樣版引擎 TemplatePower
// 使用template組成html後再輸出
$tpl=new TemplatePower("template.tpl");
$tpl-> prepare();
// 組合版面內容
$tpl->printToScreen();
}
/**
* 下載檔案
*/
function getDownloadFile(){
// 建立 zip 物件
$archive_file_name="archive".date('YmdHis').".zip";// 壓縮檔檔名
$zip=new ZipArchive($archive_file_name);
// 建立壓縮檔,若新增檔案失敗則拋出錯誤訊息
if($zip->open($archive_file_name, ZIPARCHIVE::CREATE )!==TRUE){
exit("cannot open <$archive_file_name>\n");
}
// 檔案基本資訊
$file_name="";
$file_path="";
try{
// 取得資料庫裡的檔案資料
$conn= getConn(DB_NAME, DB_HOST, DB_USER, DB_PASS);
$sql="select file_name, file_raw_path from fileinfo";
$rs=mysql_query($sql,$conn);
while($row=mysql_fetch_assoc($rs)){
$file_name=$row["file_name"];// 顯示的檔名
$file_path=$row["file_raw_path"];// 取得所要下載的檔案的原始路徑
// 須轉碼,才能正確取得中文檔名資料
// ref: 《PHP中file_exists()函数不支持中文文件名解决办法》
$file_path=mb_convert_encoding($file_path,'UTF-8','big5');
$file_name=mb_convert_encoding($file_name,'UTF-8','big5');
$zip-> addFile($file_path,$file_name);
}
// 壓縮檔案
$zip->close();
$file_size=filesize($archive_file_name);
// 判斷瀏覽器,以解決檔案下載遇有中文檔名時會亂碼的問題
// ref: 《ASP.NET 如何設定強制下載檔案並正確處理中文檔名的問題》
if(strpos($_SERVER["HTTP_USER_AGENT"],"MSIE")==true){$file_name=rawurlencode($archive_file_name);}
// 寫入檔頭執行下載
header('Pragma: no-cache');
header('Expires: 0');
header('Last-Modified: '.gmdate('D, d M Y H:i ').' GMT');
header('Content-Type: application/zip');
header('Content-Length: '.$file_size);
header('Content-Disposition: attachment; filename="'.$archive_file_name.'";');
header('Content-Transfer-Encoding: binary');
// 讀出檔案,讓使用者下載
readfile($archive_file_name);
// 關閉資料庫連線
close_conn($conn);
// 刪除產生的實體壓縮檔案
unlink($archive_file_name);
}
// 關閉資料庫連線
catch(Exception $e){ close_conn($conn);}
}
?>
文章標籤
全站熱搜
留言列表