I am trying to zip and download files from a folder named \"upload\". Zip file is downloading but I couldn\'t open (extract) it. I am getting an error like \"The archive is eith
$files = "upload/".array('Dear GP.docx','ecommerce.doc');
Should be:
$files = array('upload/Dear GP.docx','upload/ecommerce.doc');
If you are still having issues then you should check if you have write permission to the current directory. You can check the return value of close()
to check whether the file was actually written.
$res = $zip->close();
var_dump($res);
The output should be bool(true)
if the write was successful.
Looks like you have a the wrong var name in the filesize()
call also:
header('Content-Length: ' . filesize($zipfilename));
Should probably be:
header('Content-Length: ' . filesize($zipname));
You could also add extra validation to check whether the files you are adding to the zip actually exist and before sending check the zip file exists.
Edit: Turn on display errors to help you debug locally:
ini_set('display_errors', 1);
error_reporting(E_ALL);
I had spent more than 6 hours on this downloading zip files on my mac (localhost) - Though the file was getting downloaded, I could not unzip them (getting cpgz files). Apparently, none of the solutions mentioned in stack overflow (around a variety of questions on zip file download) worked. Finally, after trial and error, I found that the following code works:
None of the people answered earlier talked about the ob_start() and where exactly you should put it. Anyway, that alone was not the answer - you need to use those three lines above ob_start() too.
$file=$zippath.$filename;
if (headers_sent()) {
echo 'HTTP header already sent';
} else {
if (!is_file($file)) {
header($_SERVER['SERVER_PROTOCOL'].' 404 Not Found');
echo 'File not found';
} else if (!is_readable($file)) {
header($_SERVER['SERVER_PROTOCOL'].' 403 Forbidden');
echo 'File not readable';
} else {
while (ob_get_level()) {
ob_end_clean();
}
ob_start();
header($_SERVER['SERVER_PROTOCOL'].' 200 OK');
header("Content-Type: application/zip");
header("Content-Transfer-Encoding: Binary");
header("Content-Length: ".filesize($file));
header('Pragma: no-cache');
header("Content-Disposition: attachment; filename=\"".basename($file)."\"");
ob_flush();
ob_clean();
readfile($file);
exit;
}
}
I have a client "download-all" button for files stored in a parallel directory on a webserver. Having similar issues to the OP, the following code was created after reading many similar posts.
The server is running php7.4 on Ubuntu 20, don't forget to install your php's version of zip, mine being php7.4-zip. The HTML uses Bootstrap 4.5.2 and font-awesome 5.13.0
<?php
if( isset( $_POST["downloadAll"] ) ){
// all folders in remote dir are given a UID as a name
$directory = "../remoteLinuxDirectory/" . $_SESSION["folderID"];
$fileNames = scandir( $directory );
// create new archive
$zip = new ZipArchive;
// create a temporary file for zip creation
$tmp_file = tempnam( $directory, $_SESSION["folderName"] );
if( $zip->open( $tmp_file, ZipArchive::CREATE ) ){
// $i = 0,1 show the dot and double dot directory in linux
$i=2;
while( $i < count( $fileNames ) ){
// addFile( 'from location', 'name of individual file')
$zip->addFile( $directory . "/" . $fileNames[ $i ], $fileNames[ $i ] );
$i++;
}
$zip->close();
// remove special characters from the about-to-be-created zip filename
$cleanName = str_replace(array( ".",",","/","\\"," "),'', $_SESSION["folderName"])
header("Content-disposition: attachment; filename=" . $cleanName . ".zip");
header('Content-type: application/zip');
// begin the zip download
readfile( $tmp_file );
// removes the temporary file created in the "../remoteLinuxDirectory/"
unlink( $tmp_file );
}else{
// can be removed, but will dump some info incase the $zip->open fails
var_dump( $tmp_file );
}
}
?>
An HTML button:
<form action="" method="post">
<button class="btn btn-primary p-2 px-3">
<input name="downloadAll" value="1" hidden>
<i class="fas fa-download"></i> Download All
</button>
</form>
Please use below code instead of $zip->addFile($file);
<?php
$zip->addFile($file_path, $filename);
?>
Answer is good but Please add these lines before header. Zip file is open in all zip software (winzip, winrar etc.)
if (headers_sent())
{
// HTTP header has already been sent
return false;
}
// clean buffer(s)
while (ob_get_level() > 0)
{
ob_end_clean();
}
$zip = new ZipArchive;
if ($zip->open('assets/myzip.zip', ZipArchive::CREATE)) {
$zip->addFile('folder/bootstrap.js', 'bootstrap.js');
$zip->addFile('folder/bootstrap.min.js', 'bootstrap.min.js');
$zip->close();
echo 'Archive created!';
header('Content-disposition: attachment; filename=files.zip');
header('Content-type: application/zip');
readfile($tmp_file);
} else {
echo 'Failed!';
}
I got this code to download files from a folder.