动态 PHP ZIP 文件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1061710/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
PHP ZIP files on the fly
提问by maraspin
What's the easiest way to zip, say 2 files, from a folder on the server and force download? Without saving the "zip" to the server.
从服务器上的文件夹压缩 2 个文件并强制下载的最简单方法是什么?无需将“zip”保存到服务器。
$zip = new ZipArchive();
//the string "file1" is the name we're assigning the file in the archive
$zip->addFile(file_get_contents($filepath1), 'file1'); //file 1 that you want compressed
$zip->addFile(file_get_contents($filepath2), 'file2'); //file 2 that you want compressed
$zip->addFile(file_get_contents($filepath3), 'file3'); //file 3 that you want compressed
echo $zip->file(); //this sends the compressed archive to the output buffer instead of writing it to a file.
Can someone verify: I have a folder with test1.doc, test2.doc, and test3.doc
有人可以验证:我有一个包含 test1.doc、test2.doc 和 test3.doc 的文件夹
with the above example - file1 (file2 and file3) might just be test1.doc, etc.
使用上面的示例 - file1(file2 和 file3)可能只是 test1.doc 等。
do I have to do anything with "$filepath1"? Is that the folder directory that holds the 3 docs?
我必须对“$filepath1”做些什么吗?那是包含 3 个文档的文件夹目录吗?
Sorry for my basic question..
对不起,我的基本问题..
回答by maraspin
Unfortunately w/ PHP 5.3.4-dev and Zend Engine v2.3.0 on CentOS 5.x I couldn't get the code above to work. An "Invalid or unitialized Zip object" error message was all I could get. So, in order to make it work, I had to use following snippet (taken from the example by Jonathan Baltazar on PHP.net manual, at the ZipArchive::open page):
不幸的是,在 CentOS 5.x 上使用 PHP 5.3.4-dev 和 Zend Engine v2.3.0 我无法使上面的代码工作。我只能得到“无效或未初始化的 Zip 对象”错误消息。因此,为了使其工作,我必须使用以下代码段(取自 Jonathan Baltazar 在 PHP.net 手册上的示例,位于 ZipArchive::open 页面):
// Prepare File
$file = tempnam("tmp", "zip");
$zip = new ZipArchive();
$zip->open($file, ZipArchive::OVERWRITE);
// Stuff with content
$zip->addFromString('file_name_within_archive.ext', $your_string_data);
$zip->addFile('file_on_server.ext', 'second_file_name_within_archive.ext');
// Close and send to users
$zip->close();
header('Content-Type: application/zip');
header('Content-Length: ' . filesize($file));
header('Content-Disposition: attachment; filename="file.zip"');
readfile($file);
unlink($file);
I know this is different than working w/ memory only - unless you have your tmp area in ram ;-) - but maybe this can help out someone else, who's struggling with the solution above, like I was; and for which performance penalty is not an issue.
我知道这与仅使用内存工作不同 - 除非您的 tmp 区域在 ram 中;-) - 但也许这可以帮助其他人,他们正在为上述解决方案而苦苦挣扎,就像我一样;并且性能损失不是问题。
回答by sakabako
Your code is very close. You need to use the file name instead of the file contents.
您的代码非常接近。您需要使用文件名而不是文件内容。
$zip->addFile(file_get_contents($filepath1), 'file1');
should be
应该
$zip->addFile($filepath1, 'file1');
http://us3.php.net/manual/en/function.ziparchive-addfile.php
http://us3.php.net/manual/en/function.ziparchive-addfile.php
If you need to add files from a variable instead of a file you can use the addFromString function.
如果您需要从变量而不是文件中添加文件,您可以使用 addFromString 函数。
$zip->addFromString( 'file1', $data );
回答by Vinko Vrsalovic
If you have access to the zip commandline utility you can try
如果您有权访问 zip 命令行实用程序,则可以尝试
<?php
$zipped_data = `zip -q - files`;
header('Content-type: application/zip');
header('Content-Disposition: attachment; filename="download.zip"');
echo $zipped_data;
?>
where files is the things you want to zip and zip the location to the zip executable.
其中 files 是您要压缩的内容并将该位置压缩到 zip 可执行文件。
This assumes Linux or similar, of course. In Windows you might be able to do similar with another compression tool, I guess.
当然,这假设是 Linux 或类似版本。我想在 Windows 中,您可能可以使用其他压缩工具执行类似操作。
There's also a zip extension, usage shown here.
回答by itsols
maraspin's Answer is what I tried. Strangely, I got it working by removing the header line that references the file size:
maraspin 的答案是我尝试过的。奇怪的是,我通过删除引用文件大小的标题行来让它工作:
header('Content-Length: ' . filesize($file));
With the above change, the code works like a breeze! Without this change, I used to get the following error message:
通过上述更改,代码工作起来就像轻而易举!如果没有此更改,我曾经收到以下错误消息:
End-of-central-directory signature not found. Either this file is not a zipfile, or it constitutes one disk of a multi-part archive. In the latter case the central directory and zipfile comment will be found on the last disk(s) of this archive.
未找到中央目录结尾签名。该文件不是一个 zipfile,或者它构成了一个多部分存档的磁盘。在后一种情况下,将在此存档的最后一个磁盘上找到中央目录和 zipfile 注释。
Test environment:
测试环境:
OS: Ubuntu 10.10 Browser: Firefox And the default LAMP stack.
操作系统:Ubuntu 10.10 浏览器:Firefox 和默认的 LAMP 堆栈。
回答by dezlov
To create ZIP files on the fly (in memory), you can use ZipFileclass from phpMyAdmin:
要动态(在内存中)创建 ZIP 文件,您可以使用phpMyAdmin 中的ZipFile类:
An example of how to use it in your own application:
如何在您自己的应用程序中使用它的示例:
Note:Your ZIP files will be limited by PHP's memory limit, resulting in corrupted archive if you exceed the limit.
注意:您的 ZIP 文件将受到 PHP 内存限制的限制,如果超出限制,则会导致存档损坏。
回答by Arkiller
itsols If you want to insert the 'Content-Length' do it like this:
itsols 如果要插入“内容长度”,请执行以下操作:
$length = filesize($file);
header('Content-Length: ' . $length);
I don't know why, but it crashes if you put it in the same line.
我不知道为什么,但是如果你把它放在同一行它会崩溃。

