PHP ZIP文件在运行中

jw5wzhpr  于 2023-05-05  发布在  PHP
关注(0)|答案(9)|浏览(160)

从服务器上的一个文件夹压缩(比如说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.

有人可以验证:我有一个包含test1.doc、test2.doc和test3.doc的文件夹
在上面的例子中-file 1(file 2和file 3)可能只是test1.doc,等等。
我需要对“$filepath1”做什么吗?这是保存3个文档的文件夹目录吗?
对不起我的基本问题。

xn1cxnb4

xn1cxnb41#

不幸的是,在CentOS 5.x上的w/ PHP 5.3.4-dev和Zend Engine v2.3.0,我无法让上面的代码工作。一个“* 无效或unitialized Zip对象 *”错误消息是我所能得到的。所以,为了使它工作,我不得不使用以下片段(摘自Jonathan Baltazar在www.example.com手册上的示例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);

我知道这是不同的工作w/内存只-除非你有你的tmp区在ram ;- )-但也许这可以帮助别人,谁的挣扎与解决方案以上,像我一样;并且性能损失不是问题。

5m1hhzi4

5m1hhzi42#

你的代码非常接近。您需要使用文件名而不是文件内容。

$zip->addFile(file_get_contents($filepath1), 'file1');

应该是

$zip->addFile($filepath1, 'file1');

http://us3.php.net/manual/en/function.ziparchive-addfile.php
如果需要从变量而不是文件添加文件,可以使用addFromString函数。

$zip->addFromString( 'file1', $data );
cnjp1d6j

cnjp1d6j3#

这对我很有效(没有任何内容写入磁盘)

$tmp_file = tmpfile(); //temp file in memory
$tmp_location = stream_get_meta_data($tmp_file)['uri']; //"location" of temp file

$zip = new ZipArchive;
$res = $zip->open($tmp_location, ZipArchive::CREATE);
$zip->addFile($filepath1, 'file1');
$zip->close();

header('Content-type: application/zip');
header('Content-Disposition: attachment; filename="download.zip"');
echo(file_get_contents($tmp_location));
mqxuamgl

mqxuamgl4#

如果您可以访问zip命令行实用程序,则可以尝试

<?php
$zipped_data = `zip -q - files`;
header('Content-type: application/zip');
header('Content-Disposition: attachment; filename="download.zip"');
echo $zipped_data;
?>

where files是你想压缩的东西,并将位置压缩到zip可执行文件中。
当然,这是假设Linux或类似的操作系统。在Windows中,你可能可以用另一个压缩工具做类似的事情,我猜。
还有一个zip extension,用法显示为here

wz8daaqr

wz8daaqr5#

Maraspin的答案是我尝试过的。奇怪的是,我通过删除引用文件大小的标题行来使它工作:

header('Content-Length: ' . filesize($file));

有了上面的更改,代码工作起来就像一阵微风!如果没有这个更改,我通常会收到以下错误消息:
找不到中心目录结尾签名。该文件不是zip文件,或者它构成了多部分存档的一个磁盘。在后一种情况下,中央目录和zipfile注解将在此存档的最后一个磁盘上找到。
测试环境:
操作系统:Ubuntu 10.10Firefox和默认的LAMP堆栈。

tf7tbtn2

tf7tbtn26#

要动态创建ZIP文件(在内存中),您可以使用phpMyAdmin中的ZipFile类:

以下是如何在您自己的应用程序中使用它的示例:

dly7yett

dly7yett7#

itsols如果你想插入'Content-Length',可以这样做:

$length = filesize($file);
header('Content-Length: ' . $length);

我不知道为什么,但如果你把它放在同一行,它就会崩溃。

368yc8dk

368yc8dk8#

在Unix系统(* 和其他系统 *)上,

你可以对@maraspin的回答应用一个简单的技巧,删除文件的 file entry(从inode“取消链接”它),然后使用之前打开的句柄发送数据。这基本上与tmpfile()所做的相同;这样你就可以“临时化”任何文件。
代码与maraspin的代码相同,直到最后几行:

// 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"');

// open a handle to the zip file.
$fp = fopen($file, 'rb');
// unlink the file. The handle will stay valid, and the disk space will remain occupied, until the script ends or all file readers have terminated and closed.
unlink($file);
// Pass the file descriptor to the Web server.
fpassthru($fp);

一旦脚本完成,或异常终止,或应用程序池被循环,或Apache子进程被回收--文件的“消失”将被正式化,其磁盘空间将被释放。

jm2pwxwz

jm2pwxwz9#

这对我很有效

$tmp = tempnam(sys_get_temp_dir(), 'data');
$zip = new ZipArchive();
$zip->open($tmp, ZipArchive::CREATE);//OVERWRITE    //CREATE
$zip->addFromString('aaa.txt', 'data');//zip on the fly 
$zip->close();
header('Content-type: application/zip');
header('Content-Disposition: attachment; filename="download.zip"');

ob_clean();
flush();

if (file_exists($tmp))
    readfile($tmp);
else
    echo 'No file';

相关问题