How do I create zip file in PHP? - php

I want to create a zip file which contains some PDFs which are saved at my server.
Here is the code I tried,
$filenamez = 'datasheets1.zip';
$zip = new ZipArchive;
if ($zip->open('datasheets1.zip', ZipArchive::CREATE) === true) {
// Add files to the zip file
for ($m = 0; $m <= $total - 1; $m++) {
$zip->addFile('datasheet' . $m, $model1[$m] . ".pdf");
}
$zip->close();
echo 'Archive created!';
header('Content-type: application/zip');
header('Content-disposition: attachment; filename="' . $filenamez . '"');
header("Content-length: " . filesize($filenamez));
readfile($filenamez);
}
When I execute this code the zip file is created and downloaded but when I open it shows following error: " this archive is either in unknown format or damaged ".

In addition to Andrei's comment, you're echoing the string 'Archived Created!', and then also setting an application/zip header, and then streaming the contents of the ZIP file to the browser. So the content of the ZIP will be polluted by having that string inserted at the top, making it corrupt.

Related

PHP Zip unable to close()

I'm trying to get a couple files from wordpress /uploads folder using php and I get this error:
Warning: ZipArchive::close(): Can't remove file: No such file or directory in /www/public_html/wp-content/plugins/insert-php-code-snippet/shortcode-handler.php(65) : eval()'d code on line 32 (relative to $zip->close(); and bellow "if")
I use a plugin to inject PHP on the page.
I basically have a couple dozens checkboxes that when I press "Generate", it gets the name of the file like 07/2019/blabla (with code I get uploads folder + extension, checkbox only hold the media location + name file).
I checked and it's creating the Zip on /uploads, .pdf files exist but it crashes on the close part and when I download and try to extract I get the archive is either in unknown format or damaged
Any advise please?
if(isset($_POST['files'])) {
$error = ""; //error holder
$upload_dir = wp_upload_dir();
if(isset($_POST['createzip'])){
$post = $_POST;
if(isset($post['files']) and count($post['files']) > 0){
// open zip
$zip_file = $upload_dir['basedir'].'/'.time().".zip";
$zip_name = time().".zip";
$zip = new ZipArchive();
if ($zip->open($zip_file, ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE) !== TRUE) {
$error .= ("An error occurred creating your ZIP file.<br>");
}
foreach ($post['files'] as $file) {
// generate filename to add to zip
$filepath = $upload_dir['basedir'].'/' . $file . '.pdf';
if (file_exists($filepath)) {
$zip->addFile($filepath) or $error .= ("ERROR: Could not add the file $filename<br>");
} else {
$error .= ("File $filepath doesnt exit.<br>");
}
}
$zip->close();
if ($zip->close() !== true ) {
die($zip->getStatusString()."\n");
}
if(file_exists($zip_file)){
$error .= $zip_file;
ob_end_clean();
// push to download the zip
header('Content-type: application/zip');
header('Content-Disposition: attachment; filename="'.$zip_name.'"');
header("Content-Length: " . filesize($zip_file));
readfile($zip_file);
unlink($zip_file);
}
}
}
}
echo $error;
After $zip->close(); I replaced all code for this:
if(file_exists($zip_file)){
header($_SERVER['SERVER_PROTOCOL'].' 200 OK');
header("Content-Type: application/zip");
header("Content-Transfer-Encoding: Binary");
header("Content-Length: ".filesize($zip_file));
header("Content-Disposition: attachment; filename=\"".basename($zip_file)."\"");
readfile($zip_file);
unlink($zip_file);
exit;
}

Readfile() has started displaying on page

Part of what's being displayed:
PKd�wL��� ���/images/image_0.jpg��ex\K��1昙�3�133���;ffff����Ԇ�����w�̼߳�cw��딎�$��Z�������&QRTB�|>��E��M5���|�~b��)�o�3�� �>s���o�'���^B�O��V ����#���Q?S#(�� 6���v4���8����vvV�sy}#�_ �O��s�o���L�7Fv.F&�ol��WV.V��?�����g�W!�/w!�������K�oLL�1`���G�p�X���T�>C�#��L��)q���s��3�g�8�p�O�?
I'm trying to download images into zip file, this is what i've got so far:
if (count($headers->images) > 0) {
$counter = 0;
$zip = new ZipArchive();
$tmpFile = "tmpFolder/tmp" . strtotime("now") . ".zip";
$zip->open($tmpFile, ZipArchive::CREATE);
foreach($headers->images as $key => $images) $zip->addFromString("/images/image_" . $counter++ . ".jpg", file_get_contents($images));
$zip->close();
if (file_exists($tmpFile)) {
$fname = basename($_POST["titleZipFile"] . ".zip");
$size = filesize($tmpFile);
header("Content-Type: archive/zip");
header("Content-Disposition: attachment; filename=$fname");
header("Content-Length: " . $size);
ob_end_clean();
readfile($tmpFile);
//unlink($tmpFile);
echo "<div id='reportMessage'><p>You have successfully save images. Please go to your folder " . $_POST["titleZipFile"] . ".zip<p></div>";
}
}
if I remove the unlink($tmpFile); line then the tmp zip is actually generated and has the images inside the zip. However it's not actually showing the zip downloading in browser.
Does any one have any ideas why this could be happening?
Try to change the header for the content type to the following. I think the header is causing the browser problems with interpreting what it is supposed to do. Try the following type.
header('Content-type: application/zip');

Why zip file can't be opened after downloaded but fine via manual transfer?

I searched and tried a few previous questions/example codes, but couldn't get this to work.
I'm trying to deliver the results to end-users via PHP code. Here is my code.
$varZipFile = $varBaseNameParts[0] . '.' . $varDate . '.zip';
$varZipDir = $varBaseNameParts[0] . '_' . $varDate;
$zip = new ZipArchive();
$zip->open($varZipFile, ZipArchive::CREATE | ZipArchive::OVERWRITE);
$zip->addFile('008.csv');
$zip->addFile('002.csv');
$zip->close(); // mark line xxx
header("Content-Type: application/zip");
header("Content-disposition: attachment;filename=$varZipFile");
header('Content-Length: ' . filesize($varZipFile)); // with or without this line, got the same error
header("Content-Type: application/force-download"); // with or without this line, got the same error
readfile($varZipFile);
I got the .zip file in my browser. However WinZip cannot open it, neither can 7-Zip. WinZip complains that "Error: Central directory not found".
Interestingly, when I manually transfer the file via WinSCP from my server to my Windows machine, I can open the file with either WinZip or 7-Zip. This indicates it works all fine to 'mark line xxx', and problems occurs in the header lines.
TIA!
Your ouput buffer may not be cleared before you try to serve the download. Try to clean the output buffer before serving the download with the ob_clean() function like this:
$zip->close(); // mark line xxx
ob_clean();
Your code is working well on my side, debug this $varBaseNameParts[0] to see if the value is correct or try the below code.
// $name = name of the archive
// $archive_directory = directory to save the archive
// $file_array = list of files
function create_archive($name, $archive_directory, $file_array) {
$target_file = $archive_directory . '/' . $name . date('m-d-y').date('h-i-sa') . '.zip';
$zip = new ZipArchive();
if (count($file_array)) {
if ($zip->open($target_file, ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE)) {
foreach ($file_array as $file) {
$zip->addFile($file);
}
$zip->close();
chmod($target_file, 0777);
return $target_file;
}
}
return null;
}
function create_download($archive) {
$file_name = basename($archive);
header("Content-Type: application/zip");
header("Content-Disposition: attachment; filename=$file_name");
header("Content-Length: " . filesize($archive));
readfile($archive);
}
// create the archive file
$archive = create_archive('test', 'archive', ['008.csv', '002.csv']);
if ($archive) {
create_download($archive);
}

How to keep line breaks in a txt readme file when zipped by addfile in php?

I have a txt file showing copyright info and address to be zipped together with my images. I use php to do that. All works fine but when opening the ReadMe.txt after downloading the zip, all linebreaks are gone. How to keep the line breaks? The code I use:
$date = date("y-m-d");
$zip = new ZipArchive;
$download = 'pics-' . $date . '.zip';
$zip->open($download, ZipArchive::CREATE);
foreach (glob("photos/*.jpg") as $file) { /* Add appropriate path to read content of zip */
$new_filename = substr($file,strrpos($file,'/') + 1);
$zip->addFile($file,$new_filename);
//$zip->addFile($file);
}
$zip->addFile('/info/readme.txt', 'ReadMe.txt');
$zip->close();
header('Content-Type: application/zip');
header("Content-Disposition: attachment; filename = $download");
header('Content-Length: ' . filesize($download));
header("Location: $download");
Try out the following
foreach (glob("photos/*.jpg") as $file) { /* Add appropriate path to read content of zip */
$new_filename = substr($file,strrpos($file,'/') + 1);
$file=$new_filename."<br />"
$zip->addFile($file);
}

PHP download prompt script downloads to server as well

I wrote a PHP script that creates a zipfile and prompts the browser for download. Not only does it download to the client, for some reason it also creates a duplicate zipfile in my server in the same directory as this script.
I only want this script to download to the client, and not a duplicate on my server.
$layoutName = $_POST['layoutName'];
$htmlContent = $_POST['htmlContent'];
$layoutDir = 'http://myapp.com/public/views/layouts/' . $layoutName;
$zipFileName = 'Myapp-' . $layoutName . '.zip';
$decompressedFolderName = 'Myapp-' . $layoutName;
$zip = new ZipArchive();
$zip->open($zipFileName, ZipArchive::CREATE);
if($zip)
{
// Add index.html
$zip->addFromString('index.html', $htmlContent);
// Add CSS Folder
$cssContent = file_get_contents($layoutDir . '/css/default.css', false);
$zip->addFromString('css/default.css', $cssContent);
} else {
echo 'Could not create zip';
}
$zip->close();
header('Content-Type: application/octet-type');
header('Content-Disposition: attachment; filename=Myapp-' . $layoutName . '.zip');
header('Content-Length: ' . filesize($zipFileName));
ob_clean();
flush();
echo file_get_contents($zipFileName);
exit;
UPDATE
PROBLEM SOLVED. This code now works!
That was my exact problem. I changed readfile() to file_get_contents(), and now it doesn't create the file on my server.

Categories