首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何在PHP中[递归]压缩目录?

如何在PHP中[递归]压缩目录?
EN

Stack Overflow用户
提问于 2009-08-26 13:16:44
回答 11查看 111.3K关注 0票数 121

目录类似于:

代码语言:javascript
复制
home/
    file1.html
    file2.html
Another_Dir/
    file8.html
    Sub_Dir/
        file19.html

我使用的是在PHPMyAdmin http://trac.seagullproject.org/browser/branches/0.6-bugfix/lib/other/Zip.php中使用的相同的PHP Zip类。我不知道如何压缩一个目录,而不仅仅是一个文件。这是我到目前为止所知道的:

代码语言:javascript
复制
$aFiles = $this->da->getDirTree($target);
/* $aFiles is something like, path => filetime
Array
(
    [home] => 
    [home/file1.html] => 1251280379
    [home/file2.html] => 1251280377
    etc...
)

*/
$zip = & new Zip();
foreach( $aFiles as $fileLocation => $time ){
    $file = $target . "/" . $fileLocation;
    if ( is_file($file) ){
        $buffer = file_get_contents($file);
        $zip->addFile($buffer, $fileLocation);
    }
}
THEN_SOME_PHP_CLASS::toDownloadData($zip); // this bit works ok

但是当我尝试解压缩相应的下载zip文件时,我得到“不允许操作”。

这个错误只发生在我尝试在我的mac上解压时,当我通过命令行解压缩文件时,解压正常。我是否需要在下载时发送特定的内容类型,目前是'application/zip‘

EN

回答 11

Stack Overflow用户

回答已采纳

发布于 2009-08-26 14:07:00

这是一个简单的函数,可以递归地压缩任何文件或目录,只需要加载zip扩展名。

代码语言:javascript
复制
function Zip($source, $destination)
{
    if (!extension_loaded('zip') || !file_exists($source)) {
        return false;
    }

    $zip = new ZipArchive();
    if (!$zip->open($destination, ZIPARCHIVE::CREATE)) {
        return false;
    }

    $source = str_replace('\\', '/', realpath($source));

    if (is_dir($source) === true)
    {
        $files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($source), RecursiveIteratorIterator::SELF_FIRST);

        foreach ($files as $file)
        {
            $file = str_replace('\\', '/', $file);

            // Ignore "." and ".." folders
            if( in_array(substr($file, strrpos($file, '/')+1), array('.', '..')) )
                continue;

            $file = realpath($file);

            if (is_dir($file) === true)
            {
                $zip->addEmptyDir(str_replace($source . '/', '', $file . '/'));
            }
            else if (is_file($file) === true)
            {
                $zip->addFromString(str_replace($source . '/', '', $file), file_get_contents($file));
            }
        }
    }
    else if (is_file($source) === true)
    {
        $zip->addFromString(basename($source), file_get_contents($source));
    }

    return $zip->close();
}

这样叫它:

代码语言:javascript
复制
Zip('/folder/to/compress/', './compressed.zip');
票数 265
EN

Stack Overflow用户

发布于 2014-01-10 20:10:11

还有另一种递归目录树归档,作为ZipArchive的扩展实现。此外,还包含了一个单语句树压缩辅助函数。像在其他ZipArchive函数中一样,支持可选的本地名称。处理要添加的代码时出错...

代码语言:javascript
复制
class ExtendedZip extends ZipArchive {

    // Member function to add a whole file system subtree to the archive
    public function addTree($dirname, $localname = '') {
        if ($localname)
            $this->addEmptyDir($localname);
        $this->_addTree($dirname, $localname);
    }

    // Internal function, to recurse
    protected function _addTree($dirname, $localname) {
        $dir = opendir($dirname);
        while ($filename = readdir($dir)) {
            // Discard . and ..
            if ($filename == '.' || $filename == '..')
                continue;

            // Proceed according to type
            $path = $dirname . '/' . $filename;
            $localpath = $localname ? ($localname . '/' . $filename) : $filename;
            if (is_dir($path)) {
                // Directory: add & recurse
                $this->addEmptyDir($localpath);
                $this->_addTree($path, $localpath);
            }
            else if (is_file($path)) {
                // File: just add
                $this->addFile($path, $localpath);
            }
        }
        closedir($dir);
    }

    // Helper function
    public static function zipTree($dirname, $zipFilename, $flags = 0, $localname = '') {
        $zip = new self();
        $zip->open($zipFilename, $flags);
        $zip->addTree($dirname, $localname);
        $zip->close();
    }
}

// Example
ExtendedZip::zipTree('/foo/bar', '/tmp/archive.zip', ZipArchive::CREATE);
票数 21
EN

Stack Overflow用户

发布于 2013-02-13 13:17:21

我已经编辑了Alix Axel的答案,以获取第三个参数,当这个第三个参数设置为true时,所有的文件都将被添加到主目录下,而不是直接添加到压缩文件夹中。

如果zip文件存在,该文件也将被删除。

示例:

代码语言:javascript
复制
Zip('/path/to/maindirectory','/path/to/compressed.zip',true);

第三种true压缩结构:

代码语言:javascript
复制
maindirectory
--- file 1
--- file 2
--- subdirectory 1
------ file 3
------ file 4
--- subdirectory 2
------ file 5
------ file 6

第三个参数false或缺少zip结构:

代码语言:javascript
复制
file 1
file 2
subdirectory 1
--- file 3
--- file 4
subdirectory 2
--- file 5
--- file 6

编辑代码:

代码语言:javascript
复制
function Zip($source, $destination, $include_dir = false)
{

    if (!extension_loaded('zip') || !file_exists($source)) {
        return false;
    }

    if (file_exists($destination)) {
        unlink ($destination);
    }

    $zip = new ZipArchive();
    if (!$zip->open($destination, ZIPARCHIVE::CREATE)) {
        return false;
    }
    $source = str_replace('\\', '/', realpath($source));

    if (is_dir($source) === true)
    {

        $files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($source), RecursiveIteratorIterator::SELF_FIRST);

        if ($include_dir) {

            $arr = explode("/",$source);
            $maindir = $arr[count($arr)- 1];

            $source = "";
            for ($i=0; $i < count($arr) - 1; $i++) { 
                $source .= '/' . $arr[$i];
            }

            $source = substr($source, 1);

            $zip->addEmptyDir($maindir);

        }

        foreach ($files as $file)
        {
            $file = str_replace('\\', '/', $file);

            // Ignore "." and ".." folders
            if( in_array(substr($file, strrpos($file, '/')+1), array('.', '..')) )
                continue;

            $file = realpath($file);

            if (is_dir($file) === true)
            {
                $zip->addEmptyDir(str_replace($source . '/', '', $file . '/'));
            }
            else if (is_file($file) === true)
            {
                $zip->addFromString(str_replace($source . '/', '', $file), file_get_contents($file));
            }
        }
    }
    else if (is_file($source) === true)
    {
        $zip->addFromString(basename($source), file_get_contents($source));
    }

    return $zip->close();
}
票数 12
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1334613

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档