4

这对大多数人来说可能是一个愚蠢的问题,但我有以下文件夹,我想压缩它。

FolderI
   Folder1
   Folder2
   Folder3
   ..
   ..
   FolderN

现在,由于在线资源如此之多,特别是这里,压缩FolderI成一个zipFile.zip非常容易!但是,我想创建zipFile.zip,包含Folder1...FolderN,这样当文件被解压缩时,它会直接用Folder1...FolderN, 而不是create 填充当前目录FolderI,其中包含Folder1...FolderN

我一直在尝试的一些事情是:

$zip = new ZipArchive();

// open archive 
if ($zip->open('my-archive.zip', ZIPARCHIVE::CREATE) !== TRUE) {
    die ("Could not open archive");
}

// initialize an iterator
// pass it the directory to be processed
$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator("FolderI/"));

// iterate over the directory
// add each file found to the archive
foreach ($iterator as $key=>$value) {
    $zip->addFile(realpath($key), $key) or die ("ERROR: Could not add file: $key");
}

// close and save archive
$zip->close();

这是使用 php 脚本从compress/archive 文件夹中提取的,我试图改变它。但是没有用 - FolderI 仍然是压缩的。但是,当我解压缩时my-archive.zip,我得到一个FolderI然后Folder1..FolderN在里面。我还在这里某处看到了来自@Alix 的代码,它做了同样的事情。但是,并没有真正关注太多。

任何形式的帮助都会很棒。如果不是代码,至少指出我正确的方向。

谢谢

****这里有人知道怎么做吗?****

@Mods 和管理员:解决方案是否太简单或 PHP 根本无法做到这一点?

4

2 回答 2

2

这里出现的问题是$key迭代器中的 是完整路径(因为RecursiveDirectoryIterator::KEY_AS_PATHNAME默认使用该标志),其中包括 RecursiveDirectoryIterator 构造函数中指定的相对部分。

例如,我们有以下层次结构:

folderI
├─ folder1
│  ├─ item.php
│  └─ so.php
└─ folder2
   └─ item.html

和一个用new RecursiveDirectoryIterator("folderI").

当您回显时,$key您将获得以下信息item.php

folderI/folder1/item.php

同样,如果我们这样做new RecursiveDirectoryIterator("../somewhere/folderI"),那么$key看起来像:

../somewhere/folderI/folder1/item.php

您希望获取文件的路径,而不包括用于创建迭代器的路径。值得庆幸的是,RecursiveDirectoryIterator 有一个方法,其生命中的唯一目的就是做到这一点。

RecursiveDirectoryIterator::getSubPathname()

您可以使用以下内容,这将更容易

$newKey = $iterator->getSubPathname();

item.php鉴于上面显示的相同文件夹结构,这将返回以下内容:

folder1/item.php

该方法可以像这样使用:

foreach ($iterator as $key=>$value) {
    $zip->addFile(realpath($key), $iterator->getSubPathname()) or die ("ERROR: Could not add file: $key");
}

另外:我们可以$iterator->getSubPathname()在这里使用,因为 RecursiveIteratorIterator 将对未知方法的任何调用传递给“内部迭代器”,在本例中是 RecursiveDirectoryIterator。同样,你可以做$iterator->getInnerIterator()->getSubPathname(),两者都做同样的工作。

于 2013-03-15T19:56:24.473 回答
1

就方向而言,我可以提供:

这对我来说看起来有点过于复杂,但您可以通过添加一个 foreach 循环来创建这些迭代器,如下所示:

foreach (glob('./*', GLOB_ONLYDIR) as $dir_name) {
   // iterator
   // add file
}

Glob 可能会为您做更多的事情,可能会消除那些迭代器对象,而只支持迭代 glob 输出。

于 2013-03-14T22:14:33.257 回答