試著產生 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);}
}

?>
arrow
arrow

    小攻城師 發表在 痞客邦 留言(0) 人氣()