php Symfony2 创建和下载 zip 文件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20268025/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 03:00:36  来源:igfitidea点击:

Symfony2 create and download zip file

phpsymfonyzip

提问by BrunoRamalho

I have one application that upload some files and then I can compress as zip file and download.

我有一个应用程序可以上传一些文件,然后我可以将其压缩为 zip 文件并下载。

The export action:

导出操作:

public function exportAction() {
        $files = array();
        $em = $this->getDoctrine()->getManager();
        $doc = $em->getRepository('AdminDocumentBundle:Document')->findAll();
        foreach ($_POST as $p) {
            foreach ($doc as $d) {
                if ($d->getId() == $p) {
                    array_push($files, "../web/".$d->getWebPath());
                }
            }
        }
        $zip = new \ZipArchive();
        $zipName = 'Documents-'.time().".zip";
        $zip->open($zipName,  \ZipArchive::CREATE);
        foreach ($files as $f) {
            $zip->addFromString(basename($f),  file_get_contents($f)); 
        }

        $response = new Response();
    $response->setContent(readfile("../web/".$zipName));
    $response->headers->set('Content-Type', 'application/zip');
    $response->header('Content-disposition: attachment; filename=../web/"'.$zipName.'"');
    $response->header('Content-Length: ' . filesize("../web/" . $zipName));
    $response->readfile("../web/" . $zipName);
    return $response;
    }

everything is ok until the line header. and everytime I'm going here I got the error: "Warning: readfile(../web/Documents-1385648213.zip): failed to open stream: No such file or directory"

一切正常,直到行标题。每次我去这里时都会收到错误消息:“警告:readfile(../web/Documents-1385648213.zip):无法打开流:没有这样的文件或目录”

What is wrong?

怎么了?

and why when I upload the files, this files have root permissions, and the same happens for the zip file that I create.

以及为什么当我上传文件时,这些文件具有 root 权限,而我创建的 zip 文件也会发生同样的情况。

采纳答案by BrunoRamalho

solved:

解决了:

$zip->close();
header('Content-Type', 'application/zip');
header('Content-disposition: attachment; filename="' . $zipName . '"');
header('Content-Length: ' . filesize($zipName));
readfile($zipName);

apparently closing the file is important ;)

显然关闭文件很重要;)

回答by Vincent Moulene

SYMFONY 3 - 4 example :

SYMFONY 3 - 4 示例:

use Symfony\Component\HttpFoundation\Response;

/**
* Create and download some zip documents.
*
* @param array $documents
* @return Symfony\Component\HttpFoundation\Response
*/
public function zipDownloadDocumentsAction(array $documents)
{
    $files = [];
    $em = $this->getDoctrine()->getManager();

    foreach ($documents as $document) {
        array_push($files, '../web/' . $document->getWebPath());
    }

    // Create new Zip Archive.
    $zip = new \ZipArchive();

    // The name of the Zip documents.
    $zipName = 'Documents.zip';

    $zip->open($zipName,  \ZipArchive::CREATE);
    foreach ($files as $file) {
        $zip->addFromString(basename($file),  file_get_contents($file));
    }
    $zip->close();

    $response = new Response(file_get_contents($zipName));
    $response->headers->set('Content-Type', 'application/zip');
    $response->headers->set('Content-Disposition', 'attachment;filename="' . $zipName . '"');
    $response->headers->set('Content-length', filesize($zipName));

    @unlink($zipName);

    return $response;
}

回答by Tomá? Votruba

Since Symfony 3.2+can use file helperto let file download in browser:

由于Symfony 3.2+可以使用文件助手让文件在浏览器中下载:

public function someAction()
{
    // create zip file
    $zip = ...;

    $this->file($zip);    
}

回答by Юра Панчук

Work for me. Where $archive_file_name = 'your_path_to_file_from_root/filename.zip'.

为我工作。其中 $archive_file_name = 'your_path_to_file_from_root/filename.zip'。

$zip = new \ZipArchive();

if ($zip->open($archive_file_name, \ZIPARCHIVE::CREATE | \ZIPARCHIVE::OVERWRITE) === TRUE) {
  foreach ($files_data as $file_data) {

    $fileUri = \Drupal::service('file_system')->realpath($file_data['file_url']);
    $filename = $file_data['folder'] . $file_data['filename'];
    $zip->addFile($fileUri, $filename);
  }
  $zip->close();
}


$response = new Response();

$response->headers->set('Cache-Control', 'private');
$response->headers->set('Content-type', 'application/zip');
$response->headers->set('Content-Disposition', 'attachment; filename="' . basename($archive_file_name) . '"');
$response->headers->set('Content-length', filesize($archive_file_name));

// Send headers before outputting anything.
$response->sendHeaders();
$response->setContent(readfile($archive_file_name));
return $response;

回答by Amine

I think its better that you use

我认为你使用它更好

$zipFilesIds = $request->request->get('zipFiles')
foreach($zipFilesIds as $zipFilesId){
  //your vérification here 
}

with the post variable of your id of zip = 'zipFiles'. Its better of fetching all $_POST variables.

使用 zip = 'zipFiles' id 的 post 变量。最好获取所有 $_POST 变量。

回答by Alessandro Giuliani

To complete vincent response, just add this right before returning response :

要完成文森特响应,只需在返回响应之前添加以下内容:

...
$response->headers->set('Content-length', filesize($zipName));

unlink($zipName);

return $response;