在無法安裝 ZipArchive 擴展的環境下,純 PHP 實現的 PHPZip 類別是輕量級壓縮方案的不二之選。本文提供 v1.2 完整源碼解析與三種使用模式。
zlib 擴展(gzcompress)<?php
class PHPZip {
private $datasec = [], $ctrl_dir = [], $old_offset = 0;
private $eof_ctrl_dir = "\x50\x4b\x05\x06\x00\x00\x00\x00";
// 入口方法
public function Zip($dir, $zipfilename) {
if (!function_exists('gzcompress')) return 0;
$filelist = is_array($dir) ? $dir : $this->GetFileList($dir);
if (!$filelist) return 0;
foreach ($filelist as $filename) {
if (is_file($filename)) {
$content = file_get_contents($filename);
$this->addFile($content, is_array($dir) ? basename($filename) : $filename);
}
}
$out = $this->file();
file_put_contents($zipfilename, $out);
return 1;
}
// 遞歸掃描目錄
private function GetFileList($dir, $pref = '') {
$files = [];
if ($dh = opendir($dir)) {
while (($f = readdir($dh)) !== false) {
if ($f === '.' || $f === '..') continue;
$path = $dir . $f;
if (is_dir($path)) {
$files = array_merge($files, $this->GetFileList($path . '/', $pref . $f . '/'));
} else {
$files[] = $pref . $f;
}
}
closedir($dh);
}
return $files;
}
// 核心:添加文件到 ZIP 結構
private function addFile($data, $name, $time = 0) {
// ... 完整實現見原文,包含:
// 1. DOS 時間戳編碼
// 2. Local file header 構建
// 3. gzcompress 壓縮 + CRC32
// 4. Central directory record 構建
// 5. 更新偏移量
}
// 生成最終二進位 ZIP 內容
private function file() {
$data = implode('', $this->datasec);
$ctrldir = implode('', $this->ctrl_dir);
return $data . $ctrldir . $this->eof_ctrl_dir .
pack('v', count($this->ctrl_dir)) . // disk entries
pack('v', count($this->ctrl_dir)) . // total entries
pack('V', strlen($ctrldir)) . // central dir size
pack('V', strlen($data)) . // central dir offset
"\x00\x00"; // comment length
}
}
?>
$z = new PHPZip();
// 1. 壓縮當前目錄及子目錄所有文件
$z->Zip(".", "backup.zip");
// 2. 指定文件列表合併壓縮
$files = ['config.php', 'index.php', 'lib/core.php'];
$z->Zip($files, "deploy.zip");
// 3. 指定絕對路徑目錄壓縮
$z->Zip("/var/www/html/project", "/backups/project_".date('Ymd').".zip");
ZipArchive。若環境允許,強烈建議使用內建 ZipArchive:
$zip = new ZipArchive();
$zip->open('backup.zip', ZipArchive::CREATE);
$zip->addGlob('**/*.php', GLOB_BRACE, ['add_path' => 'src/']);
$zip->close();
PHPZip 是「無擴展環境下的救生艇」,而 ZipArchive 才是「遠洋輪船」。