可以将 7-zip 的标准输出提供给 PHP 脚本吗?

Posted

技术标签:

【中文标题】可以将 7-zip 的标准输出提供给 PHP 脚本吗?【英文标题】:Possible to feed stdout of 7-zip to PHP script? 【发布时间】:2011-06-03 12:37:05 【问题描述】:

我想使用 7-Zip 压缩目录,然后将其下载到网络浏览器。

但是,不是压缩到一个文件,而是让 php 将该文件的内容提供给浏览器......理想情况下,我希望 7-Zip 将新存档的内容写入标准输出 as正在创建存档...同时让 PHP 刷新其缓冲区并将数据发送到浏览器。

你看,我正在创建的存档非常大。从用户的角度来看,使用普通方法,当他们单击“下载”时,首先会创建存档并保存到一个文件中(可能需要大约 10 分钟),然后才可以下载 PHP 厌倦的文件.我想要做的是将归档和输出步骤合并到一个进程中。

有人对此有意见吗?

这是 SourceForge 上正在尝试做同样事情的其他人...

http://sourceforge.net/projects/p7zip/forums/forum/383043/topic/3828566

=======

感谢大家的帮助。我将关闭这个线程,因为我最近发现 *** 上已经存在关于这个主题的精彩讨论。见:

LAMP: How to create .Zip of large files for the user on the fly, without disk/CPU thrashing

=======

这是我采用的最终解决方案,它对我来说非常有效。请注意,我使用的是“InfoZip”程序,您几乎可以在任何平台上找到它。

header('Content-Type: application/zip');
header('Content-disposition: attachment; filename="file.zip"');
header('Content-Transfer-Encoding: binary');
header('Accept-Ranges: bytes');

passthru("zip -8 -q -r - ./some_directory | cat");

【问题讨论】:

尝试将存档设置为dev/stdout? (假设是 linux) 7za 可执行文件是否将压缩数据发送到它的标准输出?你需要先得到它。 执行以下操作:“7za a -lr -mx0 -so ./davedir/”会导致:“错误:我不会将压缩数据写入终端。” 那是因为您没有将结果传送到任何地方。不过,它有 -so 选项是有原因的。它足够聪明,不会把它吐出来并用垃圾填满你的屏幕。 php 中的 passthru 函数应该将标准输出从 7z 传输出去并允许它运行。值得一试。 On-the-fly zipping & streaming of large files, in PHP or otherwise的可能重复 【参考方案1】:

您可以尝试使用带有 -so(将数据写入标准输出)选项的 passthru 运行 7z。

只要您发送 7zip mime 类型的下载标头和内容类型标头,我相信它会起作用。

例子

<?php
$filename = "somefile.7z";
$contentType = "application/x-7z-compressed";
header("Content-type: ".$contentType); // tell the browser your sending a 7zip file
header("Content-Disposition: attachment; filename=\"".$filename."\""); // use 'attachment' to force a download
passthru('/path/to/7z a -so <fileOrDirToBe7Zipped>');
?>

希望有帮助!

【讨论】:

当我这样做时:“7za a -so ./davedir”... 我得到这个:“错误:我不会将压缩数据写入终端。”我可以期望这在从终端运行时不起作用,但在通过 PHP 的 passthru 函数时会成功吗? 在你的命令行上,如果你简单地尝试 "7za a -so './davedir' > davedir.7z 会发生什么 @tambler 你的权利,尽管有 -so 选项,7za 似乎没有输出到标准输出。呃……你有理由必须使用 7z,而不是其他压缩方法吗? 我刚刚发布了我开始使用的最终代码。到目前为止,它工作得很好。 我在 Linux 下尝试过 7z v9.20。它失败并出现以下错误:7z a -so / &gt; /dev/null Creating archive stdout System error: E_NOTIMPL【参考方案2】:

这是我采用的最终解决方案,它对我来说非常有效。请注意,我使用的是“InfoZip”程序,您几乎可以在任何平台上找到它。

header('Content-Type: application/zip');
header('Content-disposition: attachment; filename="file.zip"');
header('Content-Transfer-Encoding: binary');
header('Accept-Ranges: bytes');

passthru("zip -8 -q -r - ./some_directory | cat");

【讨论】:

【参考方案3】:

这要么行不通,要么出现可怕的错误。网络实际上并不是这样工作的——许多浏览器将无法正确处理不完整的文件(这是他们将要得到的)。为什么不显示“正在生成您的文件!完成后我们将通过电子邮件将下载链接发送给您。”消息,或“请稍候,我们正在生成您的文件。这可能需要几分钟。”消息以及进度条?

【讨论】:

我只是想提出一个更优雅的解决方案,但如果这真的行不通,我们可能不得不这样做。 为什么不呢?此方法在生成页面时工作得很好,并且在工作时从 7zip 获取输出也应该工作。他不是在发送不完整的文件,而是在生成文件时发送它。当然,假设 7zip 从头到尾写入文件,我相信这是这里问题的一部分。请澄清。 是的。我的意图是让 7zip 压缩一个目录,并让 PHP 在生成数据时将其刷新到浏览器......从头到尾。 我可能是错的,但即使它有效,对用户来说也会是一种奇怪且不直观的体验——没有“进度”测量的下载持续 10 分钟或更长时间。我还希望某些浏览器会轮询文件的大小,并在达到该长度时停止,从而导致文件损坏/不完整。看起来你在这里设置了一个潜在的失败点而没有真正的收获。

以上是关于可以将 7-zip 的标准输出提供给 PHP 脚本吗?的主要内容,如果未能解决你的问题,请参考以下文章

如何让php执行shell

7-zip的标准输入输出(STDIN,STDOUT)与Ncat的配合使用,压缩后传输文件

如何在使用“ls”命令以及将输出分配给变量时抑制标准错误?

Perl - 从外部进程直接输出到标准输出(避免缓冲)

在 php 中更改输出的 mime 类型

如何将麦克风输入作为标准输入提供给 C 程序