Это может быть глупый вопрос для большинства, но у меня есть следующая папка, которую я хочу заархивировать.
FolderI Folder1 Folder2 Folder3 .. .. FolderN
Теперь, FolderI
в zipFile.zip
, довольно легко из-за большого количества ресурсов в Интернете, особенно здесь! Но я хочу создать zipFile.zip
, содержащий Folder1...FolderN
, так что когда файл распакуется, он будет напрямую заполнять текущий каталог Folder1...FolderN
, вместо создания 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-скрипта, и я попытался изменить его. Не работает, но FolderI все еще застегнут. Но, когда я разархивирую my-archive.zip
, я получаю FolderI
а затем Folder1..FolderN
внутри него . Я также видел здесь код от @Alix, который сделал то же самое. Но, на самом деле, не следовало многого.
Любая помощь будет отличной. Если не код, по крайней мере, указать мне в правильном направлении.
благодаря
**** Кто-нибудь знает, как это сделать? ****
@Mods and Admins: Является ли решение слишком простым или PHP не может этого сделать вообще?
Проблема, которая здесь возникает, заключается в том, что $key
в итераторе является полным путем (поскольку по умолчанию используется флаг RecursiveDirectoryIterator::KEY_AS_PATHNAME
), который включает относительную часть, указанную в конструкторе RecursiveDirectoryIterator.
Так, например, у нас есть следующая иерархия:
folderI ├─ folder1 │ ├─ item.php │ └─ so.php └─ folder2 └─ item.html
Итератор, созданный с помощью new RecursiveDirectoryIterator("folderI")
.
Когда вы item.php
$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 передает любые вызовы неизвестным методам «внутреннему итератору», который в этом случае является рекурсивнымDirectoryIterator. Точно так же вы можете сделать $iterator->getInnerIterator()->getSubPathname()
, оба выполняют ту же работу.
Что касается направлений, я могу предложить следующее:
Это выглядит немного сложнее для меня, как есть, но вы можете нагромождать, добавив цикл foreach для создания таких итераторов:
foreach (glob('./*', GLOB_ONLYDIR) as $dir_name) { // iterator // add file }
Glob, вероятно, может сделать намного больше для вас, возможно, устранит те итерационные объекты в пользу простое повторение вывода glob.