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.
Related
I'm trying to create zip file from a large folder which size almost 2GB. My code is working well on the localhost but it's not working on the server(Cpanel). In server, it's creating a zip file which size is only 103 MB out of 2GB. According to my strategy, first of all, I'm creating a backup folder recursively named "system_backup". And the backup folder is creating well without any problem. The next is, to create the zip file of 'system_backup' folder by calling the function ZipData and stored it to another folder. In this time, it's not creating the zip file properly.
After that, the function rrmdir will be called. And it will delete the 'system_backup' folder recursively. And the deletion is not working properly as well. And, in localhost, it works well.
Then, when I'm trying to download the created zip file by the function download_file, it also not download properly. It's downloaded as a broken zip file. And, in localhost, it also works well.
I have already checked the read and write permission of folders and files.
The code is given below:-
public function backup_app(){
//Backup System
ini_set('memory_limit', '-1');
set_time_limit(0);
$this->recurse_copy(FCPATH,'system_backup');
$backup_name = 'Customs-system-backup-on_'. date("Y-m-d-H-i-s") .'.zip';
$path = FCPATH.'system_backup';
$destination = FCPATH.'bdCustomsBackup/'.$backup_name;
$this->zipData($path, $destination);
//Delete directory
$this->rrmdir($path);
$message = "Application Backup on ".date("Y-m-d-H-i-s");
$this->submit_log($message);
echo 1;
}
function zipData($source, $destination) {
if (extension_loaded('zip')) {
if (file_exists($source)) {
$zip = new ZipArchive();
if ($zip->open($destination, ZIPARCHIVE::CREATE)) {
$source = realpath($source);
if (is_dir($source)) {
$iterator = new RecursiveDirectoryIterator($source);
// skip dot files while iterating
$iterator->setFlags(RecursiveDirectoryIterator::SKIP_DOTS);
$files = new RecursiveIteratorIterator($iterator, RecursiveIteratorIterator::SELF_FIRST);
$counter = 1;
foreach ($files as $file) {
$file = realpath($file);
if (is_dir($file)) {
$zip->addEmptyDir(str_replace($source . '/', 'system_backup/', $file . '/'));
} else if (is_file($file)) {
$zip->addFromString(str_replace($source . '/', 'system_backup/', $file), file_get_contents($file));
}
}
} else if (is_file($source)) {
$zip->addFromString(basename($source), file_get_contents($source));
}
}
return $zip->close();
}
}
return false;
}
public function recurse_copy($src,$dst) {
$dir = opendir($src);
#mkdir($dst);
while(false !== ( $file = readdir($dir)) ) {
if (( $file != '.' ) && ( $file != '..' ) && ( $file != $dst ) && ( $file != "bdCustomsBackup" )) {
if ( is_dir($src . '/' . $file) ) {
$this->recurse_copy($src . '/' . $file, $dst . '/' . $file);
}
else {
copy($src . '/' . $file,$dst . '/' . $file);
}
}
}
closedir($dir);
}
public function rrmdir($src) {
$dir = opendir($src);
while(false !== ( $file = readdir($dir)) ) {
if (( $file != '.' ) && ( $file != '..' )) {
$full = $src . '/' . $file;
if ( is_dir($full) ) {
$this->rrmdir($full);
}
else {
unlink($full);
}
}
}
closedir($dir);
rmdir($src);
}
public function download_file($file){
$message = "Download ".$file." on ".date("Y-m-d-H-i-s");
$this->submit_log($message);
$path = FCPATH.'bdCustomsBackup/'.$file;
$this->load->helper('download_helper');
force_download($file, $path);
}
Here is the custom download_helper:-
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
if ( ! function_exists('force_download'))
{
function force_download($filename = '', $file = '')
{
if ($filename == '' OR $file == '')
{
return FALSE;
}
// Try to determine if the filename includes a file extension.
// We need it in order to set the MIME type
if (FALSE === strpos($filename, '.'))
{
return FALSE;
}
// Grab the file extension
$x = explode('.', $filename);
$extension = end($x);
// Load the mime types
#include(APPPATH.'config/mimes'.EXT);
// Set a default mime if we can't find it
if ( ! isset($mimes[$extension]))
{
$mime = 'application/octet-stream';
}
else
{
$mime = (is_array($mimes[$extension])) ? $mimes[$extension][0] : $mimes[$extension];
}
// Generate the server headers
if (strpos($_SERVER['HTTP_USER_AGENT'], "MSIE") !== FALSE)
{
header('Content-Type: "'.$mime.'"');
header('Content-Disposition: attachment; filename="'.$filename.'"');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header("Content-Transfer-Encoding: binary");
header('Pragma: public');
header("Content-Length: ".filesize($file));
}
else
{
header('Content-Type: "'.$mime.'"');
header('Content-Disposition: attachment; filename="'.$filename.'"');
header("Content-Transfer-Encoding: binary");
header('Expires: 0');
header('Pragma: no-cache');
header("Content-Length: ".filesize($file));
}
readfile_chunked($file);
die;
}
}
if ( ! function_exists('readfile_chunked'))
{
function readfile_chunked($file, $retbytes=TRUE)
{
$chunksize = 1 * (1024 * 1024);
$buffer = '';
$cnt =0;
$handle = fopen($file, 'r');
if ($handle === FALSE)
{
return FALSE;
}
while (!feof($handle))
{
$buffer = fread($handle, $chunksize);
echo $buffer;
ob_flush();
flush();
if ($retbytes)
{
$cnt += strlen($buffer);
}
}
$status = fclose($handle);
if ($retbytes AND $status)
{
return $cnt;
}
return $status;
}
}
/* End of file download_helper.php */
/* Location: ./application/helpers/download_helper.php */
The below code is using PHP:
$zip = new ZipArchive;
if ($zip->open('test_new.zip', ZipArchive::CREATE) === TRUE)
{
// Add files to the zip file
$zip->addFile('test.txt');
$zip->addFile('test.pdf');
// Add random.txt file to zip and rename it to newfile.txt
$zip->addFile('random.txt', 'newfile.txt');
// Add a file new.txt file to zip using the text specified
$zip->addFromString('new.txt', 'text to be added to the new.txt file');
// All files are added, so close the zip file.
$zip->close();
}
Explanation of code
Line 1 creates an object of the ZipArchive class
Line 2 opens a file with filename as test_new.zip so that we can add files to it. The flag ZipArchive::CREATE specifies that we want to create a new zip file
Lines 5 & 6 are used to add files to the zip file
Line 9 is used to add a file with name random.txt to the zip file and rename it in the zipfile as newfile.txt
Line 12 is used to add a new file new.txt with contents of the file as ‘text to be added to the new.txt file’
Line 15 closes and saves the changes to the zip file
Note: Sometimes there can be issues when using relative paths for files. If there are any issues using paths then we can also use absolute paths for files
Overwrite an existing zip file
If you want to overwrite an existing zip file then we can use code similar to following. The flag ZipArchive::OVERWRITE overwrites the existing zip file.
$zip = new ZipArchive;
if ($zip->open('test_overwrite.zip', ZipArchive::OVERWRITE) === TRUE)
{
// Add file to the zip file
$zip->addFile('test.txt');
$zip->addFile('test.pdf');
// All files are added, so close the zip file.
$zip->close();
}
Explanation of code
This code will create a file test_overwrite.zip if it already exists the file will be overwritten with this new file
Create a new zip file and add files to be inside a folder
$zip = new ZipArchive;
if ($zip->open('test_folder.zip', ZipArchive::CREATE) === TRUE)
{
// Add files to the zip file inside demo_folder
$zip->addFile('text.txt', 'demo_folder/test.txt');
$zip->addFile('test.pdf', 'demo_folder/test.pdf');
// Add random.txt file to zip and rename it to newfile.txt and store in demo_folder
$zip->addFile('random.txt', 'demo_folder/newfile.txt');
// Add a file demo_folder/new.txt file to zip using the text specified
$zip->addFromString('demo_folder/new.txt', 'text to be added to the new.txt file');
// All files are added, so close the zip file.
$zip->close();
}
Explanation of code
The above code will add different files inside the zip file to be inside a folder demo_folder
The 2nd parameter to addfile function can be used to store the file in a new folder
The 1st parameter in the addFromString function can be used to store the file in a new folder
Create a new zip file and move the files to be in different folders
$zip = new ZipArchive;
if ($zip->open('test_folder_change.zip', ZipArchive::CREATE) === TRUE)
{
// Add files to the zip file
$zip->addFile('text.txt', 'demo_folder/test.txt');
$zip->addFile('test.pdf', 'demo_folder1/test.pdf');
// All files are added, so close the zip file.
$zip->close();
}
Explanation of code
We store the file test.txt into demo_folder and test.pdf into demo_folder1
Create a zip file with all files from a directory
$zip = new ZipArchive;
if ($zip->open('test_dir.zip', ZipArchive::OVERWRITE) === TRUE)
{
if ($handle = opendir('demo_folder'))
{
// Add all files inside the directory
while (false !== ($entry = readdir($handle)))
{
if ($entry != "." && $entry != ".." && !is_dir('demo_folder/' . $entry))
{
$zip->addFile('demo_folder/' . $entry);
}
}
closedir($handle);
}
$zip->close();
}
Explanation of code
Lines 5-16 opens a directory and creates a zip file with all files within that directory
Line 5 opens the directory
Line 7 gets the name of each file in the dir
Line 9 skips the “.” and “..” and any other directories
Line 11 adds the file into the zip file
Line 14 closes the directory
Line 17 closes the zip file
I am creating script zipping files from an array.
/* 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;
}
}
#Mysql connect
$files_to_zip = array();
while($row = mysql_fetch_assoc($shots)) {
$files_to_zip[] = '/home/username/domains/example.com/public_html/components/items/images/item/' . $row["name"] . '_thb.' . $row["ext"];
}
if(isset($_POST['create'])){
//if true, good; if false, zip creation failed
$result = create_zip($files_to_zip,'my-archive5.zip');
}
After form submitting zip is created, but there's full directory tree inside files.
How to only zip files without directories?
Second thing:
When I open zip in total commander - I can see directories and files. When I open it normally - zip is empty.
The second argument to the addFile() method is the name of the file inside the zip. You're doing this:
$zip->addFile($file, $file);
So you're getting something like:
$zip->addFile('/path/to/some/file', '/path/to/some/file');
Which just copies the path from the source into the zip. If you want all the files to be in one dir in the zip, remove the path from the file name:
$zip->addFile($file, basename($file));
This will give you:
$zip->addFile('/path/to/some/file', 'file');
Note this won't work too well if you have files with the same name in different directories.
Check the docs on addFile method of Zip extension. You can specify local name as second argument.
Example from the documentation
<?php
$zip = new ZipArchive;
if ($zip->open('test.zip') === TRUE) {
$zip->addFile('/path/to/index.txt', 'newname.txt');
$zip->close();
echo 'ok';
} else {
echo 'failed';
}
?>
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 .
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("*");
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;
}
}
// using function as
include('functions.php');
$files_to_zip = array(
'database/350-001(3.1).examdb',
'setup/ExaminationEngine.exe'
);
//if true, good; if false, zip creation failed
$result = create_zip($files_to_zip,'my-archive.zip');
I am using this function to make zip.
Every thing is working perfect but the files that are created under zip file is created by full path i want only my two file in my-archive.php. but inside my-archive.php datbase/350-001(3.1).examdb and setup/ExaminationEngine.exe database and setup folder is created.
How can i fix this?
try
//add the files
foreach($valid_files as $file) {
$zip->addFile($file,basename($file));
}
instead of
//add the files
foreach($valid_files as $file) {
$zip->addFile($file,$file);
}
second argument of addFile is 'local path', basename of $file is what you want to pass to it (I assume that right now you are passing some kind of relative path)
Remember that you will have to manually assert that your filenames are unique.
see
http://php.net/manual/en/ziparchive.addfile.php
http://php.net/manual/en/function.basename.php
I recommend that you prepare a temporary folder, copy the files from different locations in there, zip it, and remove the temporary folder. Doing otherwise sounds pretty boring.