2010-06-20 43 views
16

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

在此先感谢。

+1

的这个问题的答案就在这里:http://stackoverflow.com/a/4357904/416630 – Lee 2012-11-23 18:12:26

回答

5

如果您使用的是zip extension,答案似乎是“不”。 close method in the ZipArchive class是触发写入的东西,它似乎要写入文件。你可能运用Streams来模拟一个文件,但是你将整个东西保存在内存中,并且在你添加完文件之前仍然无法发送它。

如果您在同时具有一个用户等待的zip文件被创建与超时或其他问题的问题,尝试了多步下载过程:

  1. 用户挑选不管他们挑来创建zip
  2. 它们被带到一个状态页面,该页面使用ajax调用来在后台实际构建zip文件。一个漂亮的,分散注意力的动画应该引起他们的注意。
  3. 后台进程构建zip后,用户被重定向到执行下载/重定向到文件的脚本。
11

如果你的Web服务器运行Linux,那么你可以做流而不产生的临时文件。在win32下,你可能需要使用Cygwin或类似的东西。

如果使用“ - ”作为zip文件名,它将压缩为stdout。从那里,很容易使用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); 
    } 
?> 
1

是的,你可以使用这个混帐代表直接流的压缩到客户端:Zip Stream Large Files

+0

似乎不能在windows下工作 – Jerry 2016-07-21 10:26:05