當前位置: 首頁> 最新文章列表> 如何利用php的zip_read函數結合scandir()函數,遞歸創建目標文件夾結構並實現文件解壓?

如何利用php的zip_read函數結合scandir()函數,遞歸創建目標文件夾結構並實現文件解壓?

M66 2025-06-15

在PHP中處理ZIP壓縮文件時, zip_read()函數可以幫助我們逐條讀取壓縮包內的內容。而配合scandir()函數進行遞歸文件夾操作,我們可以方便地在服務器端實現一個自動解壓ZIP文件並保留其目錄結構的功能。本文將詳細介紹如何通過這兩個函數構建這樣的腳本。

一、環境準備

確保你的PHP環境已經開啟了zip擴展。如果沒有開啟,可以通過編輯php.ini文件,找到如下配置行並取消註釋:

 extension=zip

然後重啟你的Web服務器。

二、基本思路

  1. 打開ZIP文件;

  2. 遍歷ZIP中的每一個條目;

  3. 判斷條目是否為目錄或文件;

  4. 使用scandir()結合自定義函數遞歸創建目錄結構;

  5. 將ZIP中的文件寫入目標路徑。

三、代碼實現

<?php

function createDirRecursive($path) {
    if (!is_dir($path)) {
        mkdir($path, 0777, true);
    }
}

function unzipWithStructure($zipFilePath, $destination) {
    $zip = zip_open($zipFilePath);

    if (is_resource($zip)) {
        while ($zip_entry = zip_read($zip)) {
            $entryName = zip_entry_name($zip_entry);
            $fullPath = $destination . '/' . $entryName;

            // 如果是目錄,則創建
            if (substr($entryName, -1) === '/') {
                createDirRecursive($fullPath);
            } else {
                // 確保文件所在目錄存在
                $dirPath = dirname($fullPath);
                createDirRecursive($dirPath);

                if (zip_entry_open($zip, $zip_entry)) {
                    $fileContent = zip_entry_read($zip_entry, zip_entry_filesize($zip_entry));
                    file_put_contents($fullPath, $fileContent);
                    zip_entry_close($zip_entry);
                }
            }
        }
        zip_close($zip);
    } else {
        echo "無法打開ZIP文件: $zipFilePath";
    }
}

// 使用示例
$zipPath = '/var/www/html/uploads/sample.zip';
$extractTo = '/var/www/html/extracted';

// 調用函數進行解壓
unzipWithStructure($zipPath, $extractTo);
?>

四、目錄遍歷與驗證

使用scandir()可進一步驗證目標目錄結構是否被正確創建。例如:

 function listAllFiles($dir) {
    $files = scandir($dir);
    foreach ($files as $file) {
        if ($file === '.' || $file === '..') continue;
        $path = $dir . '/' . $file;
        if (is_dir($path)) {
            echo "目錄: $path\n";
            listAllFiles($path);
        } else {
            echo "文件: $path\n";
        }
    }
}

listAllFiles('/var/www/html/extracted');

執行上述代碼後,可以輸出所有被解壓出來的文件和文件夾,方便調試和驗證。

五、注意事項

  • 所有路徑應使用絕對路徑以避免權限或路徑錯誤;

  • 在生產環境中,應注意ZIP文件的來源,防止目錄穿越攻擊(例如ZIP 中含有../../ );

  • 可結合realpath()對路徑進行規範化處理;

  • 如果文件較大,建議使用流式讀取方式處理,防止內存溢出。

六、應用場景

這個腳本適用於上傳壓縮文件並自動解壓的功能,如用戶上傳一個包含多層目錄結構的ZIP文件到m66.net/upload ,後台可直接通過以上腳本在m66.net/storage目錄下還原完整結構,並進一步處理內容,如生成縮略圖、掃描病毒或做備份。

通過這種方式,可以極大簡化內容上傳及文件初始化的工作流程,提高開發效率。