Создание и загрузка ZipArchive завершается неудачно на PHP 5.1, работает на PHP 5.4
В следующем классе происходит сбой с ошибкой ZipArchive 23 - "Запись была удалена" при попытке добавить новый пустой каталог, вложенный в другой добавленный пустой каталог. Пример:
dir1:
file1
file2
...
работает просто отлично, но как то так:
dir1:
dir2:
file1
...
file1
file1
...
потерпит неудачу при попытке добавить dir1/dir2
,
Класс загрузчика
class Downloader {
var $path, $tmp, $zip, $txt, $selected;
function __construct($selected) {
global $webroot;
$this->path = $webroot.'downloads/';
$this->tmp = tempnam('../tmp', 'dln');
$this->zip = new ZipArchive();
$this->zip->open($this->tmp, ZipArchive::OVERWRITE);
$this->txt = '';
$this->selected = $selected;
}
public function incl_file($name) {
$this->zip->addFile($this->path.$name, $name);
}
public function incl_dir($name) {
$this->zip->addEmptyDir($name);
$files = new DirectoryIterator($this->path.$name.'/');
foreach ($files as $file) {
if (!$file->isDot()) {
if ($file->isDir()) {
$this->incl_dir($name.'/'.$file->getFilename());
} else {
$this->incl_file($name.'/'.$file->getFilename());
}
}
}
}
public function download($downloadObj) {
$selected = preg_split('/,/', $this->selected);
foreach ($selected as $name) {
$this->txt .= file_get_contents($this->path.$name.'.snip');
foreach ($downloadObj->files as $file) {
if ($name == $file->name) {
// check to see if there are files to include
if (strlen($file->incl_files) > 0) {
// if so, get include directories
$incl_dirs = preg_split('/,/', $file->incl_dir);
// iterate include directories
foreach ($incl_dirs as $dir) {
// get include file groups
$incl_file_groups = preg_split('/,/', $file->incl_files);
// iterate include file groups
foreach ($incl_file_groups as $group) {
// get individual include files
$incl_files = preg_split('/\|/', $group);
// iterate individual include files
foreach ($incl_files as $f) {
// check to see if all files in include dir should be inserted
if ($f == '*') {
$this->incl_dir($dir);
} else {
$path = '';
if ($dir == "/") {
$path = $f;
} else {
$path .= $dir.'/'.$f;
}
$this->incl_file($path);
}
}
}
}
}
}
}
}
$this->txt = file_get_contents($this->path.'header.inc').$this->txt.file_get_contents($this->path.'footer.inc');
$this->zip->addFromString('DownloadTemplate.xml', $this->txt);
$this->zip->close();
$filename = 'MyDownload.zip';
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: ' . gmdate('D,d M YH:i:s') . ' GMT');
header('Cache-Control: no-cache, must-revalidate');
header('Pragma: no-cache');
header('Content-type: application/zip');
header('Content-Disposition: attachment; filename='.$filename);
header('Content-Transfer-Encoding: binary');
readfile($this->tmp);
unlink($this->tmp);
}
}
2 ответа
После многих отладок и тестирования различных опций выясняется, что проблема заключалась в вызове addEmptyDir()
, По какой-то причине, на которую я до сих пор не нашел ответа, вызов не смог добавить каталог в Zip. Тем не менее, я обнаружил, что вызов был ненужным, так как addFile()
создаст необходимые каталоги, когда им дан относительный путь, например 'dir1/file1'
, Зная это, я просто убрал призыв addEmptyDir()
и смог правильно сгенерировать zip-файл с соответствующими каталогами.
Pre-PHP 5.2 zip
был установлен с помощью разных средств. Поэтому, когда вы обновились до версии 5.4, вы, вероятно, скомпилировали или установили расширение zip с помощью PHP и не имели его на 5.1