我正在尝试为一个相对较小的 Web 应用程序集成一个按需备份系统,该系统允许用户下载服务器上所有文件的 zip 文件和数据库转储。zip 文件流式传输给用户,而不是作为一个整体打包在服务器上的临时目录中。
我正在使用名为 ZipStream 的第三方 PHP 类来完成此操作。课程托管在这里,具体的课程文件可以在这里查看。我选择了这个版本(还有另一个旧版本),因为它支持包含目录。shell_exec()
此外,该设置应该可以在服务器上运行,而无需通过或访问 shell 命令passthru()
。
我的简单测试设置正在运行,我可以使用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.
我在 StackOverflow的此处和此处找到了有关此问题的一些可能解释,我想修补 ZipStream 类以遵守 Zip 规范,以便存档实用程序将按预期扩展存档。
ZipStream 类中的“需要提取的版本”(存储在ATTR_VERSION_TO_EXTRACT
常量中)是:x0Ax00
,但我不确定该表示法是否与0x000A
上述问题中提到的标准不同。
该问题似乎与添加到 zip 文件的目录有关。仅包含文本文件的 zip 文件不会导致使用存档实用程序出现问题。
由于这与 PHP 领域的边缘一起移动,我不确定如何使用正确的十六进制字符串编辑脚本或如何将 Zend 解决方案适用于这个特定的脚本。
我在这里上传了一个生成的 zip:http: //dl.dropbox.com/u/6887873/test.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();
编辑:
我想我已经把问题缩小了一点。看起来十六进制字符串实际上并没有什么不同。使用存档实用程序展开生成的仅包含文本文件的 zip 而不会出错,因此在添加目录时似乎会发生损坏,特别addDirectoryContent()
是在调用addLargeFile()
ZipStream 类时。目录添加正确,不会导致文件无效,只要addDirectoryContent()
添加到混合存档实用程序无法提取文件,输出上述错误。