PHP 中的压缩流

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3078266/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 08:38:12  来源:igfitidea点击:

Zip Stream in PHP

phpzipstream

提问by user371254

I have a PHP script that creates a zip file on the fly and forces the browser to download the zip file. The question is: could I directly write the zip file to an output stream which is connected to the user's browser rather than save it as a real file on the server first and then send the file?

我有一个 PHP 脚本,可以动态创建一个 zip 文件并强制浏览器下载 zip 文件。问题是:我可以直接将 zip 文件写入连接到用户浏览器的输出流,而不是先将其保存为服务器上的真实文件,然后再发送文件吗?

Thanks in advance.

提前致谢。

回答by weasel5i2

If your web server is running linux, then you CAN do it streaming without a temp file being generated. Under win32 you may need to use Cygwin or something similar.

如果您的 Web 服务器正在运行 linux,那么您可以在不生成临时文件的情况下进行流式传输。在 win32 下,您可能需要使用 Cygwin 或类似的东西。

If you use "-" as the zip file name, it will compress to stdout. From there, it's easy enough to redirect that stream using popen(). The "-q" argument simply tells zip to not output the status text it normally would. See the zip(1) manpage for more info.

如果您使用“-”作为 zip 文件名,它将压缩为标准输出。从那里,很容易使用 popen() 重定向该流。“-q”参数只是告诉 zip 不要输出它通常会输出的状态文本。有关详细信息,请参阅 zip(1) 联机帮助页。

<?
     $zipfilename = "zip_file_name.zip";

     if( isset( $files ) ) unset( $files );

     $target = "/some/directory/of/files/you/want/to/zip";

     $d = dir( $target );

     while( false !== ( $entry = $d->read() ) )
     {
       if( substr( $entry, 0, 1 ) != "." && !is_dir( $entry ) ) 
       {
         $files[] = $entry;
       }
     }

     header( "Content-Type: application/x-zip" );
     header( "Content-Disposition: attachment; filename=\"$zipfilename\"" );

     $filespec = "";

     foreach( $files as $entry )
     {
       $filespec .= "\"$entry\" ";
     }

     chdir( $target );

     $stream = popen( "/usr/bin/zip -q - $filespec", "r" );

     if( $stream )
     {
       fpassthru( $stream );
       fclose( $stream );
     }
?>

回答by Andreas Gohr

This library seems to be what you're looking for: https://github.com/maennchen/ZipStream-PHP

这个库似乎是你要找的:https: //github.com/maennchen/ZipStream-PHP

回答by Charles

If you're using the zip extension, the answer seems to be "no." The close method in the ZipArchive classis what triggers a write, and it seems to want to write to a file. You mighthave some luck using Streamsto simulate a file, but then you're keeping the entire thing in memory, and you still couldn't send it until you're done adding files.

如果您使用zip 扩展名,答案似乎是否定的。ZipArchive 类中close 方法是触发写入的方法,它似乎想要写入文件。您可能会使用Streams来模拟一个文件,但随后您将整个内容保存在内存中,并且在您完成添加文件之前仍然无法发送它。

If you're having problems with timeouts or other problems while having a user wait for the zip file to be created, try a multi-step download process:

如果您在让用户等待创建 zip 文件时遇到超时或其他问题,请尝试多步骤下载过程:

  1. User picks whatever they pick to create the zip
  2. They're taken to a status page that uses ajax calls to actually build the zip file in the background. A pretty, distracting animation should keep their attention.
  3. After the background processes build the zip, the user is redirected to a script that performs the download / redirected to the file.
  1. 用户选择他们选择的任何东西来创建 zip
  2. 他们被带到一个状态页面,该页面使用 ajax 调用在后台实际构建 zip 文件。一个漂亮的、分散注意力的动画应该吸引他们的注意力。
  3. 在后台进程构建 zip 后,用户被重定向到执行下载/重定向到文件的脚本。

回答by Artur Grigio

Yes, you can directly stream the zip to the client using this git rep: Zip Stream Large Files

是的,您可以使用此 git rep 将 zip 直接流式传输到客户端:Zip Stream Large Files

回答by Artefacto

No, you have to use a temporary file, as in here.

不,你必须使用一个临时文件,在这里