I'm trying to create a zip file with the ZipArchive class. I was reading a lot here and there and implemented a lot of checks (file existence, directory writable..). But zip->close() still returns 'false' and I can't figure out why.
if (!is_writable('../temp_downloads/')) {
die('directory not writable'); }
function create_zip($files = array(),$destination = '',$overwrite = false) {
$destination = "../temp_downloads/".$destination.".zip";
if(file_exists($destination) && !$overwrite) { return false; }
$valid_files = array();
if(is_array($files)) {
foreach($files as $file) {
if(file_exists('../data/'.$file) && is_readable('../data/'.$file)) {
$valid_files[] = $file;
}
}
}
if(count($valid_files)) {
$zip = new ZipArchive();
if($zip->open($destination,$overwrite ? ZIPARCHIVE::OVERWRITE : ZIPARCHIVE::CREATE) !== true) {
exit('cannot create zip');
}
foreach($valid_files as $file) {
$zip->addFile($file,$file); // result returns 'true'
}
$res = $zip->close(); //$res contains 'false'
if(file_exists($destination)){
error_log("zip exists ".$destination);
header("Content-type: application/zip");
header("Content-Disposition: attachment; filename=$destination");
header("Content-length: " . filesize($destination));
header("Pragma: no-cache");
header("Expires: 0");
readfile("$destination");
} else {
error_log("ERROR: Zip doesnt exist at ".$destination);
}
return file_exists($destination);
} else {
return false;
}
}
I call this function with
create_zip($files, 'PREFIX_'.$stamp, true);
where $files is an array and $stamp just a timestamp.
For testing the destination folders chmod is set to 777
Could you help me?
You're (maybe?) using incorrect paths for your files in the zip operations:
Here you look for ../data/$file:
if(file_exists('../data/'.$file) && is_readable('../data/'.$file)) {
$valid_files[] = $file;
But at zipping time, you have just:
$zip->addFile($file,$file);
instead of
$zip->addFile("../data/$file",$file);
I don't see how addFile could return true, unless you coincidentally happen to have duplicates of all those files in the script's current working directory, or you ARE working in a data directory and ../data is the same as .
Related
I am using the ZipArchive class to create a ZIP file and stream it to the client but all archives are not generated correctly.
Any suggestions?
<?php
if(file_exists('../../../thure/uploads/nestingen/58861.pdf'))
{
$files = array('../../../thure/uploads/nestingen/58861.pdf');
$zipname = 'file.zip';
$zip = new ZipArchive;
$zip->open($zipname, ZipArchive::CREATE);
foreach ($files as $file) {
$zip->addFile($file);
}
$zip->close();
header('Content-Type: application/zip');
header('Content-disposition: attachment; filename='.$zipname);
header('Content-Length: ' . filesize($zipname));
readfile($zipname);
exit;
}
else
{
echo 'file not found';
}
?>
Function (writed by David)
/* creates a compressed zip file */
function create_zip($files = array(),$destination = '',$overwrite = false) {
//if the zip file already exists and overwrite is false, return false
if(file_exists($destination) && !$overwrite) { return false; }
//vars
$valid_files = array();
//if files were passed in...
if(is_array($files)) {
//cycle through each file
foreach($files as $file) {
//make sure the file exists
if(file_exists($file)) {
$valid_files[] = $file;
}
}
}
//if we have good files...
if(count($valid_files)) {
//create the archive
$zip = new ZipArchive();
if($zip->open($destination,$overwrite ? ZIPARCHIVE::OVERWRITE : ZIPARCHIVE::CREATE) !== true) {
return false;
}
//add the files
foreach($valid_files as $file) {
$zip->addFile($file,$file);
}
//debug
//echo 'The zip archive contains ',$zip->numFiles,' files with a status of ',$zip->status;
//close the zip -- done!
$zip->close();
//check to make sure the file exists
return file_exists($destination);
}
else
{
return false;
}
}
Sample Usage
$files_to_zip = array(
'file1',
'file2',
'file3'
);
//if true, good; if false, zip creation failed
$result = create_zip($files_to_zip,'my-archive.zip');
I am trying to give the possiblity to an user to download an archive in wordpress, but the download don't start after the creation of the archive. I can see that my archive is created, she's available on the server. Here my code :
My "library"
<?php
function create_zip($files = array(), $destination = '', $overwrite = false) {
if(file_exists($destination) && !$overwrite) {
return false;
}
$valid_files = array();
if(is_array($files)) {
foreach($files as $file) {
if(file_exists($file)) {
$valid_files[] = $file;
}
}
}
if(count($valid_files)) {
$zip = new ZipArchive();
if($zip->open($destination,$overwrite ? ZIPARCHIVE::OVERWRITE : ZIPARCHIVE::CREATE) !== true) {
return false;
}
foreach($valid_files as $file) {
$zip->addFile($file,$file);
}
$zip->close();
return file_exists($destination);
} else {
return false;
}
}
?>
The function called by wordpress :
<?php
require "zip.php";
$customwp = plugins_url().'/customwp/';
wp_enqueue_style('tutoriels',$customwp.'css/tutoriels.css');
wp_enqueue_script('tutoriels',$customwp.'js/tutoriels.js',array('jquery'),'1.0',true);
ob_start();
$dir = ABSPATH . 'wp-content/plugins/customwp/';
$files_to_zip = array(
$dir.'zip.php'
);
$archive_name = "archive.zip";
$result = create_zip($files_to_zip, $archive_name);
header('Content-Transfer-Encoding: binary'); //Transfert en binaire (fichier).
header('Content-Disposition: attachment; filename="archive.zip"'); //Nom du fichier.
header('Content-Length: '.filesize($archive_name)); //Taille du fichier.
readfile($archive_name);
$output_string=ob_get_contents();
ob_end_clean();
return $output_string;
?>
If you can help me, don't hesitate to try !
Best regards
the final line, where you have
return $output_string;
it should be
echo $output_string;
also, although in this case it seems it doesn't affect your code, but keep in mind that output buffering doesn't buffer your header() calls, they are sent immediately. See the php page about it:
This function will turn output buffering on. While output buffering is active no output is sent from the script (other than headers), instead the output is stored in an internal buffer.
I am trying to create a zip file of all the images that are stored in a database. This is done when the user clicks on a download button. Right now, you click on the download button, the zip file is created and the window pops up asking you if you want to open the file or save it to your computer. If you open the file, it shows you all the file names (like it's supposed to). The problem is, when you try to view the images, they are all the SAME image, just with different names.
Here's my code:
/* creates a compressed zip file */
function create_zip($files = array(), $destination = '', $overwrite = false) {
//if the zip file already exists and overwrite is false, return false
if(file_exists($destination) && !$overwrite) { return false; }
//vars
$path = 'admin/ReviewFiles/';
$valid_files = array();
//if files were passed in...
if(is_array($files)) {
//cycle through each file
foreach($files as $file) {
//make sure the file exists
$fullFile = $path . $file;
if(file_exists($fullFile)) {
$valid_files[] = $file;
}
}
}
//if we have good files...
if(count($valid_files)) {
//create the archive
$zip = new ZipArchive();
if($zip->open($destination,$overwrite ? ZIPARCHIVE::OVERWRITE : ZIPARCHIVE::CREATE) !== true) {
return false;
}
//add the files
foreach($valid_files as $file) {
$zip->addFile($file);
}
//close the zip -- done!
$zip->close();
//check to make sure the file exists
return file_exists($destination);
}
else
{
return false;
}
}
And here's where the function is called:
$i = 0;
$reviewFiles = array();
while ($row = mysql_fetch_object($result))
{
$reviewFiles[$i] = $row->fileName;
$i++;
}
$zipCreated = create_zip($reviewFiles, 'reviewFiles.zip', true);
$file = 'reviewFiles.zip';
if ($zipCreated) {
header('Content-Type: application/zip');
header('Content-Disposition: attachment; filename=reviewFiles.zip');
header('Expires: 0');
header('Pragma: no-cache');
readfile("reviewFiles.zip");
exit;
}
I have tried everything I can think of to figure out why it's not actually downloading each image. So, I guess clearly put, my question is: How can I fix the code to make it actually zip each file, not just one image with the same image with different names?
Thanks!
This:
if(file_exists($fullFile)) {
$valid_files[] = $file;
}
should be:
if(file_exists($fullFile)) {
$valid_files[] = $fullFile;
}
Otherwise the files could not be found. If you have changed this, you may also wish to set a local name:
foreach($valid_files as $file) {
$zip->addFile($file, basename($file));
}
I'm using basename() to prevent zip from creating sub directories in the archive.
Im using the bellow code to create and download a zip file from all the files in the root of the folder.
Ive got this line
$files_to_zip = array(
'room1.jpg', 'room2.jpg'
);
which lets you chose which files to put into the zip file - but my files are the result of a cron job so theres a new one generated each day. How can i write a variable to say all files, apart from " " and then list the files that i dont want in the zipfolder ie. index.php ect..
so far ive tried writing $files_to_zip = *; (obviously that would not exclude any files) but that just throws up a Parse error: syntax error
this is the full code bellow:
<?php
/* creates a compressed zip file */
function create_zip($files = array(),$destination = '',$overwrite = true) {
//if the zip file already exists and overwrite is false, return false
if(file_exists($destination) && !$overwrite) { return false; }
//vars
$valid_files = array();
//if files were passed in...
if(is_array($files)) {
//cycle through each file
foreach($files as $file) {
//make sure the file exists
if(file_exists($file)) {
$valid_files[] = $file;
}
}
}
//if we have good files...
if(count($valid_files)) {
//create the archive
$zip = new ZipArchive();
if($zip->open($destination,$overwrite ? ZIPARCHIVE::OVERWRITE : ZIPARCHIVE::CREATE) !== true) {
return false;
}
//add the files
foreach($valid_files as $file) {
$zip->addFile($file,$file);
}
//debug
//echo 'The zip archive contains ',$zip->numFiles,' files with a status of ',$zip->status;
//close the zip -- done!
$zip->close();
//check to make sure the file exists
return file_exists($destination);
}
else
{
return false;
}
}
$files_to_zip = array(
'room1.jpg', 'room2.jpg'
);
//if true, good; if false, zip creation failed
$zip_name = 'my-archive.zip';
$result = create_zip($files_to_zip,$zip_name);
if($result){
header('Content-Type: application/zip');
header('Content-disposition: attachment; filename=filename.zip');
header('Content-Length: ' . filesize($zip_name));
readfile($zip_name);
}
?>
The function to do wildcard matching against the filesystem is glob().
$files_to_zip = glob("*");
I am using this function to generate zip files:
function create_zip($files = array(),$destination = '',$overwrite = false) {
//if the zip file already exists and overwrite is false, return false
if(file_exists($destination) && !$overwrite) { return false; }
//vars
$valid_files = array();
//if files were passed in...
if(is_array($files)) {
//cycle through each file
foreach($files as $file) {
//make sure the file exists
if(file_exists($file)) {
$valid_files[] = $file;
}
}
}
//if we have good files...
if(count($valid_files)) {
//create the archive
$zip = new ZipArchive();
if($zip->open($destination,$overwrite ? ZIPARCHIVE::OVERWRITE : ZIPARCHIVE::CREATE) !== true) {
return false;
}
//add the files
foreach($valid_files as $file) {
$zip->addFile($file,$file);
//echo $file;
}
//debug
//echo 'The zip archive contains ',$zip->numFiles,' files with a status of ',$zip->status;
//close the zip -- done!
$zip->close();
//check to make sure the file exists
echo $destination;
return file_exists($destination);
}
else
{
return false;
}
}
I am using this to zip a vanilla, unaltered Wordpress install.(http://wordpress.org/) However for some reason the wp-content folder is having a 'ghost' empty file generated with it's name. The folder (and everything else) itself compresses correctly, but most unzip applications (including php's own extractTo()) break when they reach this unwanted file due to the name conflict.
I've looked into the folder/file structure and as far as I can see the only difference of note between this and the other folders in the site is that it is the biggest at 5.86 mb.
Can anyone suggest a fix / workaround?
This is the sample example to zip a folder.
<?php
function Create_zipArch($archive_name, $archive_folder)
{
$zip = new ZipArchive;
if ($zip->open($archive_name, ZipArchive::CREATE) === TRUE)
{
$dir = preg_replace('/[\/]{2,}/', '/', $archive_folder . "/");
$dirs = array($dir);
while (count($dirs))
{
$dir = current($dirs);
$zip->addEmptyDir($dir);
$dh = opendir($dir);
while ($file = readdir($dh))
{
if ($file != '.' && $file != '..')
{
if (is_file($file))
$zip->addFile($dir . $file, $dir . $file);
elseif (is_dir($file))
$dirs[] = $dir . $file . "/";
}
}
closedir($dh);
array_shift($dirs);
}
$zip->close();
$result='success';
}
else
{
$result='failed';
}
return $result;
}
$zipArchName = "ZipFileName.zip"; // zip file name
$FolderToZip = "zipthisfolder"; // folder to zip
echo Create_zipArch($zipArchName, $FolderToZip);
?>