I have one application that upload some files and then I can compress as zip file and download.
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"
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.
SYMFONY 3 - 4 example :
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;
}
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 ;)
Since Symfony 3.2+ can use file helper to let file download in browser:
public function someAction()
{
// create zip file
$zip = ...;
$this->file($zip);
}
ZipArchive creates the zip file into the root directory of your website if only a name is indicated into open
function like $zip->open("document.zip", ZipArchive::CREATE)
. Specify the path into this function like $zip->open("my/path/document.zip", ZipArchive::CREATE)
. Do not forget delete this file with unlink()
(see doc).
Here you have an example in Symfony 4 (may work on earlier version):
use Symfony\Component\HttpFoundation\Response;
use \ZipArchive;
public function exportAction()
{
// Do your stuff with $files
$zip = new ZipArchive();
$zip_name = "../web/zipFileName.zip"; // Users should not have access to the web folder (it is for temporary files)
// Create a zip file in tmp/zipFileName.zip (overwrite if exists)
if ($zip->open($zip_name, ZipArchive::CREATE | ZipArchive::OVERWRITE) === TRUE) {
// Add your files into zip
foreach ($files as $f) {
$zip->addFromString(basename($f), file_get_contents($f));
}
$zip->close();
$response = new Response(
file_get_contents($zip_name),
Response::HTTP_OK,
['Content-Type' => 'application/zip',
'Content-Disposition' => 'attachment; filename="' . basename($zip_name) . '"',
'Content-Length' => filesize($zip_name)]);
unlink($zip_name); // Delete file
return $response;
} else {
// Throw an exception or manage the error
}
}
You may need to add "ext-zip": "*"
into your Composer file to use ZipArchive
and extension=zip.so
in your php.ini
.
Answser inspired by Create a Response object with zip file in Symfony.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With