無法開啟 PHP ZipArchive 下載的 zip 檔
PHP 內有一個用來操控壓縮檔的 ZipArchive 模組,今天收到問題回報說下載的 zip 檔沒辦法開啟,當下直覺認為是對方操作錯誤,給幾個同事測試之後,有一個同事同樣無法開啟,竟然是因為檔頭多了一些空白造成,這篇記錄此問題的解法。
PHP 壓縮檔案
這邊是留給自己的 ZipArchive 用法的 memo,確定載入此模組後,只要使用以下方法就可以輕鬆把檔案壓縮成 zip
// 建立 ZipArchive 物件 $zip = new ZipArchive(); // 在指定路徑中建立一個 zip 檔 $res = $zip->open('tmp_callback/123.zip', ZipArchive::CREATE); // 把 tmp_callback/file1 新增至 zip 內,並改名為 00000001.txt $zip->addFile('tmp_callback/file1', '00000001.txt'); // 關閉 zip 物件 $zip->close();
透過網頁下載 zip 檔
透過以下的語法可以讓瀏覽器直接下載 zip 檔,一方面在之前做權限控管以及避免洩漏檔案真實路徑
$path = "/var/www/html/uploads/"; $filename = '03082358.zip'; 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=\"".$filename."\""); header("Content-Transfer-Encoding: binary"); header("Content-Length: " . filesize($path . $filename)); @readfile($file);
無法開啟壓縮檔的原因
直到有使用者反應壓縮檔無法開啟,透過 unzip-online.com 線上解壓縮也失敗
使用 notepad++ 開啟後才發現 zip 檔開頭有三行空白,可是有些電腦可以正常開啟有些電腦卻不行
只要把那三行空白刪除,就可以正常解壓縮了 …
無法開啟壓縮檔的解決方法
一開始以為是 ZipArchive 模組的問題,做了各種嘗試後發現,產出來的 zip 是正常的,並沒有上面那三行空白,那問題就是出在下載這段了。
試了很多方法發現只要有<?php include_once "xxx.php" ?>
就會有三行空白的狀況,一開始笨笨的試著把所有用到的 include 都拔進來放,後來覺得這樣實在是又累又蠢,最後終於找到簡單解法 … 只要在readfile
之前呼叫ob_clean();
就可以避免這個問題 …
// 以上省略 ob_clean(); @readfile($file);