Предупреждение о закрытии ZipArchive

Я пытаюсь исправить проблему в скрипте автоматического zip для некоторых изображений, который я написал некоторое время назад, и он работал до сих пор. Все выглядит нормально, пока $zip->close(); не выдает следующее:

 <b>Warning</b>:  ZipArchive::close(): Read error: No such file or directory in <b></b> on line <b>287</b><br />

Я прочитал документы и некоторые форумы и узнал, что это может произойти в одном из следующих сценариев:

  1. If no actual files are added to the zip, since PHP 5.6—this could be a likely explanation since I recently upgraded to PHP 5.6. However:
    • I check that each file exists before adding it
    • Я попытался добавить в zip фиктивный непустой текстовый файл. Добавление его в zip возвращает true, как и file_exists() в файле.
    • Когда я повторяю $zip->numFiles, и он дает число не менее 1 (когда в zip нет файлов, кроме пустышки)
  2. Если каталог, в который нужно записать zip, не существует или не имеет правильных разрешений: похоже, это не так, но просто чтобы быть уверенным, я написал текстовый файл в ту же папку в тот же скрипт и проблем не было
  3. Если есть проблема с записью во временный каталог. Это немного сложнее проверить, но у меня есть работающий скрипт загрузки в той же системе, и я убедился, что нет проблем с местом на диске и т. д.

Вот соответствующий код. Некоторые переменные определены заранее. Обратите внимание, что я записываю каждую проблему в свой журнал, и этот скрипт не создает никаких записей!

$zip_file = 'Project'.$project_id.'.zip';
$zip = new ZipArchive;
if ($zip_result = $zip->open($zip_path.'/'.$zip_file, ZIPARCHIVE::CREATE) !== true) {
    echo 'Error creating zip for project: '.$project_id.'. Error code: '.$zip_result;
    help::debugLog('Error creating zip for project: '.$project_id.'. Error code: '.$zip_result);
    return false;
}
$file_list = array();

foreach ($item_thumbs as $item)
{
    $full_thumb_path = $thumb_dir.'/'.$item['thumb'];
    if (file_exists($full_thumb_path) and $item['thumb'])
    {
        $file_added = $zip->addFile($full_thumb_path, basename($item['thumb']));
        if (!$file_added)
            help::debugLog('Failed to add item thumb to project zip. Project: '.$project_id.', file name: '.$item['thumb']);
        else
            $file_list[] = $item['thumb'];
    }
    elseif ($item['thumb']) /* If thumb indicated in DB doesn't exist in file system */
        help::debugLog('Item thumb file '.$item['thumb'].' from item: '.$item['id'].' is missing from its indended location: '.$full_thumb_path);
}

/* Added 2016-05-18 -- creates dummy file for the zip listing its contents, important in case zip is empty */
$file_list_path = $zip_path.'/file_list.txt';
if (!($file_list_file = fopen($file_list_path, 'w+')))
    help::debugLog('Failed to create list file (intended for zip) for project: '.$project_id);
fwrite($file_list_file, "File list:\n");
fwrite($file_list_file, implode("\n", $file_list));
if (file_exists($file_list_path))
{
    fclose($file_list_file);
    if (!$zip->addFile($file_list_path))
        help::debugLog('Failed to add list file to project zip for project: '.$project_id);
    unlink($file_list_path);
}
else
    help::debugLog('Failed to create list file (intended for zip) for project: '.$project_id);

$zip->close(); // line 287

person Ynhockey    schedule 18.05.2016    source источник


Ответы (3)


Оказывается, решение было очень простым, и на него действительно ссылаются в документации (php.net) в одном из комментариев:

Кому-то это может показаться очевидным, но с моей стороны это была оплошность.

Если вы добавляете в zip-файл файлы, которые хотите удалить, убедитесь, что вы удалили ПОСЛЕ вызова функции close().

Если файлы, добавленные к объекту, недоступны во время сохранения, zip-файл не будет создан.

(Источник: https://www.php.net/manual/en/ziparchive.close.php#93322)

Таким образом, из моего кода выше фиктивный текстовый файл удаляется до закрытия почтового индекса, что обязательно означает, что файл не существует во время создания почтового индекса.

У меня были веские основания полагать, что zip был создан во временном месте и перемещен в окончательное место только close(). Оказывается, это не так.

person Ynhockey    schedule 24.05.2016
comment
Итак, как вы решили проблему в своем коде? - person Artur Grigio; 26.11.2016
comment
Я переместил $zip-›close() в точку перед удалением текстового файла. - person Ynhockey; 08.03.2017

Просто потому, что это сообщение об ошибке № 1 в Google, я добавляю еще одну возможную проблему, которая вызывает точно такую ​​​​же ошибку.

Если вы не добавите файлы в zip-архив, он еще не существует, поэтому метод close() не будет работать с пустым архивом.

eg:

$zip = new ZipArchive;
$zip->open("foo.zip", ZipArchive::CREATE | ZipArchive::OVERWRITE);
$zip->close();

производит:

ERROR: ZipArchive::close(): Can't remove file: No such file or directory

Поэтому, если вы зацикливаете и добавляете файлы, убедитесь, что вы что-то добавили перед вызовом close().

person Andreas Huttenrauch    schedule 13.04.2021

Проверьте значение «$full_thumb_path» в строке

    $file_added = $zip->addFile($full_thumb_path, basename($item['thumb']));

Значение должно быть путем к файлу и не должно быть путем к каталогу.

person Daniel Qi    schedule 25.07.2016
comment
Даже если это каталог, он не выдаст предупреждение о zip_close() в этом скрипте, если фиктивный файл не будет удален. - person Ynhockey; 25.07.2016
comment
У меня только что было это во время сборки phing. Сообщение: [Ошибка PHP] ZipArchive::close(): Ошибка чтения: Является ли каталог --› ответ прост, это просто потому, что в дереве файлов была какая-то символическая ссылка - person Nadir; 01.01.2017