我正在尝试为一个相对较小的Web应用程序集成按需备份系统,该应用程序允许用户下载服务器上所有文件的zip文件和数据库转储。 zip文件将流式传输给用户,而不是作为一个整体打包在服务器上的临时目录中。
我正在使用名为ZipStream的第三方PHP类来完成此任务。该类托管here和特定的类文件can be viewed here。我选择了这个版本(有another, older one),因为它支持包含目录。此外,设置应该可以在服务器上运行,而无需通过shell_exec()
或passthru()
访问shell命令。
我的简单测试设置正常运行,我可以使用控制台中的unzip
命令或使用The Unarchiver.app
提取生成的流式压缩文件。 OS X的归档实用程序(Mac OS X 10.6以及很可能是旧版本和更高版本)导致问题,但因为它无法提取存档而出现以下错误:
Unable to unarchive "test.zip" into "test". (Error 1 - Operation not permitted.)
记录的实际错误是:
ditto: Couldn't read pkzip signature.
我找到了一些关于这个问题的可能解释,here和here on StackOverflow,我想修补ZipStream类以遵守Zip规范,以便Archive Utility按预期扩展存档
ZipStream类中的“需要提取的版本”(存储在 ATTR_VERSION_TO_EXTRACT
常量中)是:x0Ax00
,但我不确定该符号是否与标准{ {1}}在上述问题中提及。
问题似乎与添加到zip文件的目录有关。仅包含文本文件的zip文件不会导致使用Archive Utility出现问题。
由于这与PHP领域的边缘一起移动,我不确定如何使用正确的十六进制字符串编辑脚本或如何将Zend解决方案应用于此特定脚本。
我已在此处上传了生成的zip:http://dl.dropbox.com/u/6887873/test.zip
要生成的代码是示例代码的精简版本:
0x000A
修改
我想我已经把问题缩小了一点。似乎十六进制字符串实际上没有区别。使用Archive Utility扩展包含文本文件的生成的zip没有错误,因此在添加目录时尤其是在调用$extime = ini_get('max_execution_time');
ini_set('max_execution_time', 600);
include_once("ZipStream.php");
$fileTime = date("D, d M Y H:i:s T");
$chapter1 = "Chapter 1\n"
. "Lorem ipsum\n"
. "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec magna lorem, mattis sit amet porta vitae, consectetur ut eros. Nullam id mattis lacus. In eget neque magna, congue imperdiet nulla. Aenean erat lacus, imperdiet a adipiscing non, dignissim eget felis. Nulla facilisi. Vivamus sit amet lorem eget mauris dictum pharetra. In mauris nulla, placerat a accumsan ac, mollis sit amet ligula. Donec eget facilisis dui. Cras elit quam, imperdiet at malesuada vitae, luctus id orci. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Pellentesque eu libero in leo ultrices tristique. Etiam quis ornare massa. Donec in velit leo. Sed eu ante tortor.\n";
$zip = new ZipStream("test.zip");
$zip->addFile("Hello World!\r\n", "Hello.txt");
$zip->addDirectory("files/");
$zip->addDirectoryContent("../images", "files/testing/");
$zip->finalize();
时会发生损坏,而addDirectoryContent()
又调用ZipStream类的addLargeFile()
。正确添加目录并且不会导致文件无效,只要addDirectoryContent()
添加到混合档案存档实用程序无法提取文件,输出上述错误。