LAMP:如何从远程URL /文件创建.Zip并将其流式传输到客户端

时间:2016-10-29 22:21:28

标签: php zip pipe lamp

使用S3等外部服务进行对象存储,提供存储文件的自定义zip存档的老问题变得有点复杂。一种方法是让Web服务器将所有资源复制到临时本地文件,将它们编译成.zip,然后将zip返回给用户,但这很慢且资源密集。

这可以与solution for local files类似地完成吗?例如您可以curl这些文件,在流媒体模式下将它们导入zip,然后直接发送给用户吗?

1 个答案:

答案 0 :(得分:0)

是的 - 您可以让zip操作一套fifos 而不是一组文件。这是代码:

$sh = 'mkfifo a.jpg b.jpg ; '.                     // 1
  'curl -s some_service.com/a.jpg > a.jpg & ' .    // 2
  'curl -s some_service.com/b.jpg > b.jpg & ' .    // 
  'zip -FI - a.jpg b.jpg | cat > out.fifo';        // 3

// Open output fifo & curl-zip task pipe
posix_mkfifo('out.fifo', 0777);                    // 4
$pipe_output = popen('cat out.fifo', 'r');         //
$pipe_curlzip = popen($sh, 'r');                   //

它的工作原理如下:

  1. 我们有两个远程文件:some_service.com/a.jpgsome_service.com/b.jpg - 我们为每个创建一个fifo,每个fifo都有相应文件的名称,我们希望它出现在我们的zip文件中。因此,对于some_service.com/a.jpg,我们创建了一个名为a.jpg
  2. 的fifo
  3. 启动两个curl任务,将远程文件a.jpgb.jpg提供给每个相应的fifo。这些curl任务将挂起,直到从输出fifos读取内容,因此我们在后台运行它们(&)。
  4. 开始我们的zip任务,给它两个十五作为输入。我们cat将其流输出到 third fifo - out.fifo - 以允许我们的PHP进程将文件流式传输给用户。
  5. 解决问题。
  6. 这只是一个阅读out.fifo内容并将其发送给用户的问题:

    header('Content-Type: application/octet-stream');
    header('Content-Disposition: attachment; filename="Download.zip"');
    
    while (!feof($pipe_output)) {
        echo fread($pipe_output, 128);   // Your magic number here
    }