I am looking to add both folders and files from a matching array to a zip file. Below is my code:
function listdir($start_dir='./assets') {
//Array that will contain the director
$files = array();
if (is_dir($start_dir)) {
$fh = opendir($start_dir);
while (($file = readdir($fh)) !== false) {
// Loop through the files, skipping '.' and '..', and recursing if necessary
if (strcmp($file, '.')==0 || strcmp($file, '..')==0) continue;
$filepath = $start_dir . '/' . $file;
if ( is_dir($filepath) )
$files = array_merge($files, listdir($filepath));
//else
array_push($files, $filepath);
}
closedir($fh);
} else {
// false if the function was called with an invalid non-directory argument
$files = false;
}
return $files;
}
//Array of all files
$allFiles = listdir('./assets');
print_r($allFiles);
//Gets all values with name "asset"
$name = $_POST['asset'];
//If there are items in the array, zip them together
if($name!=0){
//Compares $_POST array with array of all files in directory
$result = array_intersect($allFiles, $name);
function zipFilesAndDownload($result){
$zip = new ZipArchive();
//create the file and throw the error if unsuccessful
if ($zip->open('SelectedAssets.zip', ZIPARCHIVE::CREATE )!==TRUE) {
exit("cannot open SelectedAssets.zip\n");
}
//add each files of $file_name array to archive
foreach($result as $allFiles) {
$zip->addFile($allFiles);
}
$zip->close();
$zipped_size = filesize('SelectedAssets.zip');
header("Content-Description: File Transfer");
header("Content-type: application/zip");
header("Content-Type: application/force-download");// some browsers need this
header("Content-Disposition: attachment; filename=SelectedAssets.zip");
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header("Content-Length:". " $zipped_size");
ob_clean();
flush();
readfile("SelectedAssets.zip");
unlink("SelectedAssets.zip"); // Now delete the temp file (some servers need this option)
exit;
}
if(isset($_POST['submit'])) {
//$file_names=$_POST['assets'];// Always sanitize your submitted data!!!!!!
//$file_names = filter_var_array($_POST['assets']);//works but it's the wrong method
$filter = filter_input_array(INPUT_POST, FILTER_SANITIZE_SPECIAL_CHARS) ;
$file_names = $filter['assets'] ;
//Archive name
$archive_file_name='DEMO-archive.zip';
//Download Files path
$file_path= getcwd(). './';
//call the function
zipFilesAndDownload($result);
} else {
print 'Something went wrong.';
exit;
}
} //Otherwise, don't.
else {
print_r("Please select a file.");
}
The code above searches through a directory and reads all the folders and files. Then using array_intersect I matched files that were put into an empty array by the user to all the files in the previously searched directory. I then zip the files that match and download.
My question is, how can I have a folder be added to this zip as well? As of now, this only adds files and folders are assumed as empty.
Related
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;
}
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
The code I currently have, attached below, successfully writes files into an archive and initiates downloading of the file but the filename is a random alphanumeric string. A few examples of these file titles are:
IfTO57y8.zip
PFuuPgMD.zip
KUgWDc0T.zip
How can I set the name of the Zip folder to something more user-friendly?
function start_brochures_download( $brochures ) {
$confirmation = "Your download should begin shortly. \r\n";
$error = "Files not set \r\n";
$files = $brochures;
if( $files ) {
$zip = new ZipArchive();
$current_time = time();
$file_name = "Brochures-".$current_time;
$file_folder = wp_upload_dir();
$dir = $file_folder['path'];
$zip_file = $dir.'/'.$file_name.'.zip';
$zip->open( $zip_file, ZipArchive::CREATE );
foreach ($files as $file) {
if( !empty($file) ){
# download file
$download_file = file_get_contents($file);
#add it to the zip
$zip->addFromString(basename($file), $download_file);
}
}
$zip->close();
header('Content-disposition: attachment; filename="'.$zip_name.'"');
header('Content-type: application/zip');
header('Content-Length: ' . filesize($zip_file));
// header("Location: $zip_file");
readfile($zip_file);
} else {
echo $error;
}
}
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.
I have folder named "data". This "data" folder contains a file "filecontent.txt" and another folder named "Files". The "Files" folder contains a "info.txt" file.
So it is a folder inside folder structure.
I have to zip this folder "data"(using php) along with the file and folder inside it, and download the zipped file.
I have tried the examples available at http://www.php.net/manual/en/zip.examples.php
These examples did not work. My PHP version is 5.2.10
Please help.
I have written this code.
<?php
$zip = new ZipArchive;
if ($zip->open('check/test2.zip',ZIPARCHIVE::CREATE) === TRUE) {
if($zip->addEmptyDir('newDirectory')) {
echo 'Created a new directory';
} else {
echo 'Could not create directory';
}
$zipfilename="test2.zip";
$zipname="check/test2.zip";
header('Content-Type: application/zip');
header('Content-disposition: attachment; filename=check/test1.zip'); //header('Content-Length: ' . filesize( $zipfilename));
readfile($zipname); //$zip->close(); } else { echo failed';
}
?>
file downloaded but could not unzip
You need to recursively add files in the directory. Something like this (untested):
function createZipFromDir($dir, $zip_file) {
$zip = new ZipArchive;
if (true !== $zip->open($zip_file, ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE)) {
return false;
}
zipDir($dir, $zip);
return $zip;
}
function zipDir($dir, $zip, $relative_path = DIRECTORY_SEPARATOR) {
$dir = rtrim($dir, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
if ($handle = opendir($dir)) {
while (false !== ($file = readdir($handle))) {
if (file === '.' || $file === '..') {
continue;
}
if (is_file($dir . $file)) {
$zip->addFile($dir . $file, $file);
} elseif (is_dir($dir . $file)) {
zipDir($dir . $file, $zip, $relative_path . $file);
}
}
}
closedir($handle);
}
Then call $zip = createZipFromDir('/tmp/dir', 'files.zip');
For even more win I'd recommend reading up on the SPL DirectoryIterator here
========= The only solution for me ! ! !==========
Puts all subfolders and sub-files with their structure:
<?php
$the_folder = 'path/foldername';
$zip_file_name = 'archived_name.zip';
$download_file= true;
//$delete_file_after_download= true; doesnt work!!
class FlxZipArchive extends ZipArchive {
/** Add a Dir with Files and Subdirs to the archive;;;;; #param string $location Real Location;;;; #param string $name Name in Archive;;; #author Nicolas Heimann;;;; #access private **/
public function addDir($location, $name) {
$this->addEmptyDir($name);
$this->addDirDo($location, $name);
} // EO addDir;
/** Add Files & Dirs to archive;;;; #param string $location Real Location; #param string $name Name in Archive;;;;;; #author Nicolas Heimann
* #access private **/
private function addDirDo($location, $name) {
$name .= '/';
$location .= '/';
// Read all Files in Dir
$dir = opendir ($location);
while ($file = readdir($dir))
{
if ($file == '.' || $file == '..') continue;
// Rekursiv, If dir: FlxZipArchive::addDir(), else ::File();
$do = (filetype( $location . $file) == 'dir') ? 'addDir' : 'addFile';
$this->$do($location . $file, $name . $file);
}
} // EO addDirDo();
}
$za = new FlxZipArchive;
$res = $za->open($zip_file_name, ZipArchive::CREATE);
if($res === TRUE)
{
$za->addDir($the_folder, basename($the_folder));
$za->close();
}
else { echo 'Could not create a zip archive';}
if ($download_file)
{
ob_get_clean();
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private", false);
header("Content-Type: application/zip");
header("Content-Disposition: attachment; filename=" . basename($zip_file_name) . ";" );
header("Content-Transfer-Encoding: binary");
header("Content-Length: " . filesize($zip_file_name));
readfile($zip_file_name);
//deletes file when its done...
//if ($delete_file_after_download)
//{ unlink($zip_file_name); }
}
?>
I had to do the same thing a few days ago and here is what I did.
1) Retrieve File/Folder structure and fill an array of items. Each item is either a file or a folder, if it's a folder, retrieve its content as items the same way.
2) Parse that array and generate the zip file.
Put my code below, you will of course have to adapt it depending on how your application was made.
// Get files
$items['items'] = $this->getFilesStructureinFolder($folderId);
$archiveName = $baseDir . 'temp_' . time(). '.zip';
if (!extension_loaded('zip')) {
dl('zip.so');
}
//all files added now
$zip = new ZipArchive();
$zip->open($archiveName, ZipArchive::OVERWRITE);
$this->fillZipRecursive($zip, $items);
$zip->close();
//outputs file
if (!file_exists($archiveName)) {
error_log('File doesn\'t exist.');
echo 'Folder is empty';
return;
}
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private", false);
header("Content-Type: application/zip");
header("Content-Disposition: attachment; filename=" . basename($archiveName) . ";" );
header("Content-Transfer-Encoding: binary");
header("Content-Length: " . filesize($archiveName));
readfile($archiveName);
//deletes file when its done...
unlink($archiveName);
Methods used to fill & parse:
/**
*
* Gets all the files recursively within a folder and keeps the structure.
*
* #param int $folderId The id of the folder from which we start the search
* #return array $tree The data files/folders data structure within the given folder id
*/
public function getFilesStructureinFolder($folderId) {
$result = array();
$query = $this->db->query('SELECT * FROM xx WHERE deleted = 0 AND status = 1 AND parent_folder_id = ? ORDER BY name ASC', $folderId);
$folders = $query->result();
foreach($folders as $folder) {
$folderItem = array();
$folderItem['type'] = 'folder';
$folderItem['obj'] = $folder;
$folderItem['items'] = $this->getFilesStructureinFolder($folder->id);
$result[] = $folderItem;
}
$query = $this->db->query('SELECT * FROM xx WHERE deleted = 0 AND xx = ? AND status = 1 ORDER BY name ASC', $folderId);
$files = $query->result();
foreach ($files as $file) {
$fileItem = array();
$fileItem['type'] = 'file';
$fileItem['obj'] = $file;
$result[] = $fileItem;
}
return $result;
}
/**
* Fills zip file recursively
*
* #param ZipArchive $zip The zip archive we are filling
* #param Array $items The array representing the file/folder structure
* #param String $zipPath Local path within the zip
*
*/
public function fillZipRecursive($zip, $items, $zipPath = '') {
$baseDir = $this->CI->config->item('xxx');
foreach ($items['items'] as $item) {
//Item is a file
if ($item['type'] == 'file') {
$file = $item['obj'];
$fileName = $baseDir . '/' . $file->fs_folder_id . '/' . $file->file_name;
if (trim($file->file_name) == '' || !file_exists($fileName))
continue;
$zip->addFile($fileName, $zipPath.''.$file->file_name);
}
//Item is a folder
else if ($item['type'] == 'folder') {
$folder = $item['obj'];
$zip->addEmptyDir($zipPath.''.$folder->name);
//Folder probably has items in it!
if (!empty($item['items']))
$this->fillZipRecursive($zip, $item, $zipPath.'/'.$folder->name.'/');
}
}
}
See the linked duplicates. Another often overlooked and particular lazy option would be:
exec("zip -r data.zip data/");
header("Content-Type: application/zip");
readfile("data.zip"); // must be a writeable location though
Use the TbsZip class to create a new zip Archive. TbsZip is simple, it uses no temporary files, no zip EXE, it has no dependency, and has a Download feature that flushes the archive as a download file.
You just have to loop under the folder tree and add all files in the archive, and then flush it.
Code example:
$zip = new clsTbsZip(); // instantiate the class
$zip->CreateNew(); // create a virtual new zip archive
foreach (...) { // your loop to scann the folder tree
...
// add the file in the archive
$zip->FileAdd($FileInnerName, $LocalFilePath, TBSZIP_FILE);
}
// flush the result as an HTTP download
$zip->Flush(TBSZIP_DOWNLOAD, 'my_archive.zip');
Files added in the archive will be compressed sequentially during the Flush() method. So your archive can contain numerous sub-files, this won't increase the PHP memory.