在 PHP 5.1 上创建和下载 ZipArchive 失败,在 PHP 5.4 上有效
Creating and downloading ZipArchive fails on PHP 5.1, works on PHP 5.4
以下 class 失败并出现 ZipArchive 错误 23 - "Entry has been deleted" 尝试添加嵌套在另一个添加的空目录中的新空目录时。例如:
dir1:
file1
file2
...
工作正常,但类似于:
dir1:
dir2:
file1
...
file1
file1
...
尝试添加 dir1/dir2
时会失败。
下载器Class
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);
}
}
Pre-PHP 5.2 zip
是通过 different means 安装的。因此,当您更新到 5.4 时,您可能使用 PHP 编译或安装了 zip 扩展,而在 5.1
上没有它
经过大量调试和测试不同的选项后,问题出在对 addEmptyDir()
的调用中。出于某种原因,我仍然没有找到答案,调用未能在 Zip 中添加目录。然而,我随后发现这个调用完全没有必要,因为 addFile()
会在给定相对路径名时创建必要的目录,例如 'dir1/file1'
。知道这一点后,我刚刚删除了对 addEmptyDir()
的调用,并且能够正确生成具有适当目录的 zip 文件。
以下 class 失败并出现 ZipArchive 错误 23 - "Entry has been deleted" 尝试添加嵌套在另一个添加的空目录中的新空目录时。例如:
dir1:
file1
file2
...
工作正常,但类似于:
dir1:
dir2:
file1
...
file1
file1
...
尝试添加 dir1/dir2
时会失败。
下载器Class
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);
}
}
Pre-PHP 5.2 zip
是通过 different means 安装的。因此,当您更新到 5.4 时,您可能使用 PHP 编译或安装了 zip 扩展,而在 5.1
经过大量调试和测试不同的选项后,问题出在对 addEmptyDir()
的调用中。出于某种原因,我仍然没有找到答案,调用未能在 Zip 中添加目录。然而,我随后发现这个调用完全没有必要,因为 addFile()
会在给定相对路径名时创建必要的目录,例如 'dir1/file1'
。知道这一点后,我刚刚删除了对 addEmptyDir()
的调用,并且能够正确生成具有适当目录的 zip 文件。