無法開啟 PHP ZipArchive 下載的 zip 檔

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

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *