首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHPZip 類別完整實作:純 PHP 實現目錄壓縮、多文件合併、就地生成 .zip

     編輯:PHP 相關知識

PHPZip 類別完整實作:純 PHP 實現目錄壓縮、多文件合併、就地生成 .zip

在無法安裝 ZipArchive 擴展的環境下,純 PHP 實現的 PHPZip 類別是輕量級壓縮方案的不二之選。本文提供 v1.2 完整源碼解析與三種使用模式。

核心特性

  • 零依賴:僅需 zlib 擴展(gzcompress)
  • 支援三種模式:單文件/文件陣列/整個目錄
  • 自動處理子目錄遞歸、路徑正規化
  • 符合 ZIP 格式規範(Local header + Central directory + End record)

類別完整源碼(精簡版)

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

效能與限制提醒

  • ⚠️ 記憶體限制:全量讀取文件內容到記憶體,大文件(> 50MB)易 OOM。
  • ⚠️ 速度較慢:純 PHP 實現,大量文件壓縮耗時明顯高於 ZipArchive。
  • ✅ 適用場景:共享主機無擴展權限、中小型部署包生成、簡單備份腳本。

現代替代方案

若環境允許,強烈建議使用內建 ZipArchive:

$zip = new ZipArchive();
$zip->open('backup.zip', ZipArchive::CREATE);
$zip->addGlob('**/*.php', GLOB_BRACE, ['add_path' => 'src/']);
$zip->close();

PHPZip 是「無擴展環境下的救生艇」,而 ZipArchive 才是「遠洋輪船」。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved