首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在Symfony中使用ZipStream :流媒体压缩下载不会使用Mac上的Archive实用程序解压缩

在Symfony中使用ZipStream :流媒体压缩下载不会使用Mac上的Archive实用程序解压缩
EN

Stack Overflow用户
提问于 2017-06-22 10:48:32
回答 1查看 2.8K关注 0票数 1

我有一个Symfony2.8应用程序,在用户单击“下载”按钮时,我使用s3上几个大型(图像、视频)文件的键,使用ZipStream (https://github.com/maennchen/ZipStream-PHP)将其作为压缩文件流到浏览器。

文件流和作为zip的下载(存储,而不是压缩)在浏览器中是成功的& zip下载。但是,当尝试使用Archive ( OSX上的本机存档软件)打开Mac中的zip时,它会出错。错误:

无法将"test.zip“扩展为”下载“。(错误2-没有这样的文件或目录。)

我在SO上看到了一些老的、相同的问题,并试图修复这些问题,特别是这篇文章:https://stackoverflow.com/a/5574305/136151和后续的问题& ZipStream中的问题& PRs,相关的,以及Guzzle中的上游修复等等。

问题是,上述修正早在2011年就已经解决了,而且事情在这段时间里还在继续。因此,应用相同的修正,我没有得到一个工作的结果。

我尝试过的具体修复方法是: 1.按照建议将“版本提取”设置为0x000A。也是另一篇文章中推荐的“20”。我已经为“制作的版本”设置了相同的。2.我试图迫使压缩方法‘放气’而不是‘存储’,以确定我是否得到了一个工作结果。存储的结果是我所需要的,适合用作图像和视频的容器文件的压缩。

我可以使用第三方档案应用程序提取拉链,名为“未存档程序”。然而,用户不会知道&不能期望安装一个可供选择的存档应用程序来适应我的web应用程序。这不是一个有效的解决办法。

有没有人有解决这一问题的知识或经验,并能帮助我解决这个问题?

注:到浏览器的流压缩是必需的解决方案。将资产从s3下载到服务器以创建zip,然后将所得zip流到浏览器并不是解决方案,因为这种方法的时间和开销都很大。

如果需要,添加了信息:

代码和设置:-文件存储在s3上。- Web是Symfony2.8,在PHP7.0上使用Ubuntu运行在ec2上。-使用aws创建一个具有有效凭据的s3client,我在s3client上注册StreamWrapper (s3Client->StreamWrapper)。这是通过fopen从s3获取文件到ZipStream库:

代码语言:javascript
复制
$this->s3Client = $s3Client;  
$this->s3Client->registerStreamWrapper();

// Initialize the ZipStream object and pass in the file name which
//  will be what is sent in the content-disposition header.
// This is the name of the file which will be sent to the client.
// Define suitable options for ZipStream Archive.
$opt = array(
        'comment' => 'test zip file.',
        'content_type' => 'application/octet-stream'
      );
$zip = new ZipStream\ZipStream($filename, $opt);

$keys = array(
      "zipsimpletestfolder/file1.txt"
  );

foreach ($keys as $key) {
    // Get the file name in S3 key so we can save it to the zip file 
    // using the same name.
    $fileName = basename($key);

    $bucket = 'mg-test';
    $s3path = "s3://" . $bucket . "/" . $key;

    if ($streamRead = fopen($s3path, 'r')) {
      $zip->addFileFromStream($fileName, $streamRead);        
    } else {
      die('Could not open stream for reading');
    }
}

$zip->finish();

Zip输出结果:

  • 通过存档实用程序提取mac失败,错误2
  • 使用未存档程序对mac进行提取是有效的。
  • 从窗户上提取7-zip是有效的。
  • 使用WinRar提取窗口失败--据说zip已损坏。

响应头:

编辑I开放使用另一种将文件流到浏览器的方法,它可以在Mac、Windows、Linux上本地打开,如果建议使用ZipStream的话。只是不创建一个压缩文件服务器端,以便随后进行流处理。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-06-22 18:00:16

下载zip的问题在于它包含来自Symfony控制器中调用ZipStream->addFileFromStream()的响应的html。基本上,当ZipStream在客户端浏览器中进行数据流传输以创建zip下载时,还会发送控制器动作响应,最好的猜测是,两者在客户端浏览器上混在一起。在十六进制编辑器中打开zip文件,并在其中看到html,这显然是问题所在。

为了在Symfony 2.8中使用ZipStream,我在控制器操作中使用了Symfony的StreamedResponse,在streamedResponse的函数中使用了ZipStream。要流S3文件,我只是将s3keys和s3client的数组传递到该函数中。所以:

代码语言:javascript
复制
use Symfony\Component\HttpFoundation\StreamedResponse;
use Aws\S3\S3Client;    
use ZipStream;

//...

/**
 * @Route("/zipstream", name="zipstream")
 */
public function zipStreamAction()
{
    //test file on s3
    $s3keys = array(
      "ziptestfolder/file1.txt"
    );

    $s3Client = $this->get('app.amazon.s3'); //s3client service
    $s3Client->registerStreamWrapper(); //required

    $response = new StreamedResponse(function() use($s3keys, $s3Client) 
    {

        // Define suitable options for ZipStream Archive.
        $opt = array(
                'comment' => 'test zip file.',
                'content_type' => 'application/octet-stream'
              );
        //initialise zipstream with output zip filename and options.
        $zip = new ZipStream\ZipStream('test.zip', $opt);

        //loop keys useful for multiple files
        foreach ($s3keys as $key) {
            // Get the file name in S3 key so we can save it to the zip 
            //file using the same name.
            $fileName = basename($key);

            //concatenate s3path.
            $bucket = 'bucketname';
            $s3path = "s3://" . $bucket . "/" . $key;        

            //addFileFromStream
            if ($streamRead = fopen($s3path, 'r')) {
              $zip->addFileFromStream($fileName, $streamRead);        
            } else {
              die('Could not open stream for reading');
            }
        }

        $zip->finish();

    });

    return $response;
}

解决了。也许这有助于其他人在Symfony中使用ZipStream。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44697218

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档