Using ZipStream in Symfony: streamed zip download will not decompress using Archive Utility on Mac OSX

后端 未结 1 1468
不知归路
不知归路 2020-12-21 20:19

I have a symfony 2.8 application and on the user clicking \"download\" button, I use the keys of several large (images, video) files on s3 to stream this to the browser as a

相关标签:
1条回答
  • 2020-12-21 21:17

    The issue with the zip downloaded is that it contained html from the response in the Symfony controller that was calling ZipStream->addFileFromStream(). Basically, when ZipStream was streaming data to create zip download in client browser, a controller action response was also sent and, best guess, the two were getting mixed up on client's browser. Opening the zip file in hex editor and seeing the html in there it was obviously the issue.

    To get this working in Symfony 2.8 with ZipStream, I just used Symfony's StreamedResponse in the controller action and used ZipStream in the streamedResponse's function. To stream S3 files I just passed in an array of s3keys and the s3client into that function. So:

    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;
    }
    

    Solved. Maybe this helps someone else use ZipStream in Symfony.

    0 讨论(0)
提交回复
热议问题