ZipArchive не может разархивировать файлы, которые ZipArchive архивирует в PHP

Попытка получить функциональность импорта / экспорта.

  1. С папкой, содержащей файл
  2. Сжать папку в PHP с помощью ZipArchive
  3. Распакуйте zip-папку, используя ZipArchive
  4. Новая папка создана, но файл внутри отсутствует

    function unArchive(){
        $zip = new ZipArchive;
        $res = $zip->open('zipTest.zip');
        if ($res === TRUE) {
            echo 'ok';
            $zip->extractTo("testfolder2");
            $zip->close();
        } else {
            echo 'failed, code:' . $res;
        }
    }
    
    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('\\', '/', 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();
    }
    
    Zip( "testfolder/" , "./zipTest.zip" );
    unArchive();
    

Код отлично работает для отдельных файлов. С файлом, заархивированным с помощью ZipArchive, я могу вручную разархивировать с помощью WinRAR, затем разархивировать с помощью WinRAR, а затем ZipArchive может успешно разархивировать этот файл. Проблема в том, что ZipArchive не будет извлекать архив, который был непосредственно заархивирован. Я также вижу в Notepad++, что ZipArchive zip отличается от WinRAR zip, а размер файла отличается. Я могу успешно вызывать winrar как системную команду в php для желаемой функциональности, но это кажется плохой идеей. Есть ли какая-то причина, по которой ZipArchive создает zip-файлы, которые он не может извлечь?

Сообщение об ошибке: ZipArchive::extractTo(): неверный аргумент в [file] в строке [$zip->extractTo("testfolder2");]

1 ответ

RecursiveIteratorIterator возвращает псевдофайлы "." и, что здесь важно, ".." - родительский каталог. Когда вы используете addEmptyDir для добавления родительского каталога, ZipArchive добавит его (как угодно)! Вы можете даже попробовать "$zip->addEmptyDir("../ что-то ")", и он не будет жаловаться.

Теперь, как правило, почтовые файлы ведут себя не так. Когда вы извлекаете их, вы ожидаете, что все содержимое будет в папке, в которую вы их извлекаете, а не в родительских папках. Вот почему обычные программы извлечения ZIP не показывают это.

Однако PHP ZipArchive будет извлекать даже эти папки. Затем эта ошибка как-то произойдет, потому что вы пытались включить "." или ".." каталоги.

Добавьте это в начале цикла foreach, чтобы решить это:

if (basename($file) === ".") { continue;}
if (basename($file) === "..") { continue; }

Прецедент:

<?php
$archive = new ZipArchive();
$archive->open('c.zip',ZipArchive::CREATE);
$archive->addFile('a.txt');
$archive->addFile('b.txt');
$archive->addEmptyDir("../../down");
$archive->close();

$archive2 = new ZipArchive();
$archive2->open('c.zip');
$archive2->extractTo('here');
$archive2->close();

Я проверял это только на Windows.

Другие вопросы по тегам