Freezing folder contents in PHP

Before marking this post as a duplicate, please note that I was already looking for an answer on SO, and the one I have found so far (listed below) was not exactly what I was looking for.

  • How to [recursively] Pin a directory to PHP?
  • using zipArchive addFile () will not add the image to the zip code
  • ZipArchive - addFile will not work

These are just some of the ones I looked at.

My problem is this: I cannot use addFromString, I had to use addFile, this is a requirement of the task.

I already tried a couple of ways, here is my current iteration:

public function getZippedFiles($path) { $real_path = WEBROOT_PATH.$path; $files = new RecursiveIteratorIterator (new RecursiveDirectoryIterator($real_path), RecursiveIteratorIterator::LEAVES_ONLY); //# create a temp file & open it $tmp_file = tempnam($real_path,''); $zip_file = preg_replace('"\.tmp$"', '.zip', $tmp_file); $zip = new ZipArchive(); $zip->open($zip_file, ZipArchive::CREATE); foreach ($files as $name=>$file) { error_log(print_r($name, true)); error_log(print_r($file, true)); if ( ($file == ".") || ($file == "..") ) { continue; } $file_path = $file->getRealPath(); $zip->addFile($file_path); } $zip->close(); } 

When I try to open the resulting file, they tell me that "Windows cannot open the folder. The compressed (compressed) folder" "is invalid.

I was able to successfully complete the task using addFromString, for example:

 $file_path = WEBROOT_PATH.$path; $files = array(); if (is_dir($file_path) == true) { if ($handle = opendir($file_path)) { while (($file = readdir($handle)) !== false) { if (is_dir($file_path.$file) == false) { $files[] = $file_path."\\".$file; } } //# create new zip opbject $zip = new ZipArchive(); //# create a temp file & open it $tmp_file = tempnam($file_path,''); $zip_file = preg_replace('"\.tmp$"', '.zip', $tmp_file); $zip->open($zip_file, ZipArchive::CREATE); //# loop through each file foreach($files as $file){ //# download file $download_file = file_get_contents($file); //#add it to the zip $zip->addFromString(basename($file),$download_file); } //# close zip $zip->close(); } } } 

Above all, it’s just copied directly from some sample code that I saw somewhere. If someone can point me in a good direction, I would be very grateful!

***** UPDATE ***** I added that around: like this:

 if (!$zip->close()) { echo "failed writing zip to archive"; } 

The message gets an echo, so obviously the problem is there. I also checked to make sure $zip->open() working, and I confirmed that it opens it without problems.

+2
file php compression zip
Mar 17 '15 at 15:05
source share
2 answers

Finally managed to get something using addFile .

I created a helper class that contains 3 functions: one for listing all the files in a directory, 1 for zip all these files, and 1 for downloading archived files:

 <?php require_once($_SERVER["DOCUMENT_ROOT"]."/config.php"); class FileHelper extends ZipArchive { /** * Lists files in dir * * This function expects an absolute path to a folder intended as the target. * The function will attempt to create an array containing the full paths to * all files in the target directory, except for . and .. * * @param dir [string] : absolute path to the target directory * * @return result [array] : array of absolute paths pointing to files in the target directory */ public static function listDirectory($dir) { $result = array(); $root = scandir($dir); foreach($root as $value) { if($value === '.' || $value === '..') { continue; } if(is_file("$dir$value")) { $result[] = "$dir$value"; continue; } if(is_dir("$dir$value")) { $result[] = "$dir$value/"; } foreach(self::listDirectory("$dir$value/") as $value) { $result[] = $value; } } return $result; } /** * Zips and downloads files * * This function expects a directory location as target for a temp file, and a list(array) * of absolute file names that will be compressed and added to a zip file. After compression, * the temporary zipped file will be downloaded and deleted. * * @param location [string] : absolute path to the directory that will contain the temp file * @param file_list [array] : array of absolute paths pointing to files that need to be compressed * * @return void */ public function downloadZip($file) { $modules = apache_get_modules(); if (in_array('mod_xsendfile', $modules)) // Note, it is not possible to detect if X-SendFile is turned on or not, we can only check if the module is installed. If X-SendFile is installed but turned off, file downloads will not work { header("Content-Type: application/octet-stream"); header('Content-Disposition: attachment; filename="'.basename($file).'"'); header("X-Sendfile: ".realpath(dirname(__FILE__)).$file); // Apache will take care of the rest, so terminate the script exit; } header("Content-Type: application/octet-stream"); header("Content-Length: " .(string)(filesize($file)) ); header('Content-Disposition: attachment; filename="'.basename($file).'"'); header("Content-Transfer-Encoding: binary"); header("Expires: 0"); header("Cache-Control: no-cache, must-revalidate"); header("Cache-Control: private"); header("Pragma: public"); ob_end_clean(); // Without this, the file will be read into the output buffer which destroys memory on large files readfile($file); } /** * Zips files * * This function expects a directory location as target for a temp file, and a list(array) * of absolute file names that will be compressed and added to a zip file. * * @param location [string] : absolute path to the directory that will contain the temp file * @param file_list [array] : array of absolute paths pointing to files that need to be compressed * * @return zip_file [string] : absolute file path of the freshly zipped file */ public function zipFile($location, $file_list) { $tmp_file = tempnam($location,''); $zip_file = preg_replace('"\.tmp$"', '.zip', $tmp_file); $zip = new ZipArchive(); if ($zip->open($zip_file, ZIPARCHIVE::CREATE) === true) { foreach ($file_list as $file) { if ($file !== $zip_file) { $zip->addFile($file, substr($file, strlen($location))); } } $zip->close(); } // delete the temporary files unlink($tmp_file); return $zip_file; } } ?> 

Here is what I called these class functions:

 $location = "d:/some/path/to/file/"; $file_list = $file_helper::listDirectory($location); $zip_file = $file_helper->zipFile($location, $file_list); $file_helper->downloadZip($zip_file); 
0
Mar 18 '15 at 9:56
source share

Check out this solution, much more clearly:

 function Zip($source, $destination) { if (!extension_loaded('zip') || !file_exists($source)) { return false; } $zip = new ZipArchive(); if (!$zip->open($destination, ZIPARCHIVE::CREATE)) { return false; } $source = str_replace('\\', '/', realpath($source)); if (is_dir($source) === true) { $files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($source), RecursiveIteratorIterator::SELF_FIRST); foreach ($files as $file) { $file = str_replace('\\', '/', $file); // Ignore "." and ".." folders if( in_array(substr($file, strrpos($file, '/')+1), array('.', '..')) ) continue; $file = realpath($file); if (is_dir($file) === true) { $zip->addEmptyDir(str_replace($source . '/', '', $file . '/')); } else if (is_file($file) === true) { $zip->addFile($file, str_replace($source . '/', '', $file)); } } } else if (is_file($source) === true) { $zip->addFile($file, str_replace($source . '/', '', $file)); } return $zip->close(); } 

And use it like:

 Zip('/folder/to/compress/', './compressed.zip'); 

Mark the original post with addFromString

0
Mar 17 '15 at 15:15
source share



All Articles