我有一个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库:
$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输出结果:
响应头:

编辑I开放使用另一种将文件流到浏览器的方法,它可以在Mac、Windows、Linux上本地打开,如果建议使用ZipStream的话。只是不创建一个压缩文件服务器端,以便随后进行流处理。
发布于 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的数组传递到该函数中。所以:
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。
https://stackoverflow.com/questions/44697218
复制相似问题