how to zip folder inside it two folders using ZipArchive class - php

I'm trying to zip folder it call
Maker_100164 inside this folder two folders and two files
folder_a
folder_b
index1.php
index.php
and I'm using below function
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->addFromString(str_replace($source . '/', '', $file), file_get_contents($file));
}
}
}
else if (is_file($source) === true)
{
$zip->addFromString(basename($source), file_get_contents($source));
}
return $zip->close();
}
and when I want to call it I call it like this
$dirp = '/maker/up/users/admin/Maker_100164/';
$p = '/maker/up/users/admin/Maker_100164/Maker_100164.zip';
$zipallfolders = Zip($dirp, $p);
if($zipallfolders)
{
echo 'ok';
}else{
echo 'wrong';
}
but it doesn't work.

Related

Exclude directories & files from RecursiveDirectoryIterator

I'm trying to ZIP a folder and all its files and subfolder EXCEPT some files and folders.
I have an array of files and folders to exclude.
Works for the files, but folders in the exclude array are not excluded...
here is the code :
if(isset($_POST['tourpath'])){
$source = $_POST['tourpath'];
$cache_name = $_POST['cache_name'];
$destination = $cache_name.'.zip';
if (!extension_loaded('zip') || !file_exists($source) || file_exists($destination)) {
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);
$exclude_files = array('zipmytour.php','krpano_sworker.js','cache_settings.js','lib','b','d','f','l','r','u');
foreach ($files as $file)
{
if (!in_array($file->getFilename(),$exclude_files)) {
$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->addFromString(str_replace($source . '/', '', $file), file_get_contents($file));
}
}}
}
else if (is_file($source) === true)
{
$zip->addFromString(basename($source), file_get_contents($source));
}
return $zip->close();
}
How to also exclude folders ?
Many thx !!!
A function is useful that checks whether a directory name from an array is present in a path:
function isDirInPath(array $dirs, $path) {
$path = str_replace('\\', '/', $path);
foreach($dirs as $dir){
if(strpos($path,'/'.trim($dir,"/").'/') !== false){
return true;
}
}
return false;
}
example for the use of the function:
$files = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($source,FilesystemIterator::SKIP_DOTS),
RecursiveIteratorIterator::SELF_FIRST
);
$excludeDir = ['dir1','dir2'];
foreach($files as $path => $file){
if(!$file->isDir() AND !isDirInPath($excludeDir,$path)){
echo $file->getFileName(), '<br>';
}
}
Note: The entire path does not have to be in the $ excludeDir array. 'dir1' is sufficient to hide everything under '/foo/dir1/bar/'.

Delete files after adding them into an archive

I have a question, so I need to delete all files from a directory which I added into an archive. I need to create another methode after zip() for delete files? Or I can do simultaneously?
My code for add in archive:
define("PATH_TO_FILES_FOR_ARCHIVE","/tmp/");
define("NOM_OF_ARCHIVE","/tmp/folder.zip");
addZip(PATH_TO_FILES_FOR_ARCHIVE, NOM_OF_ARCHIVE);
function addZip($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->addFromString(str_replace($source . '/', '', $file), file_get_contents($file));
}
}
}
else if (is_file($source) === true)
{
$zip->addFromString(basename($source), file_get_contents($source));
}
return $zip->close();
}
Thx in advance.
if you just want to delete it then you can delete it using the unlink() function, there is no need to write another procedure for it.
**Edited:**
else if (is_file($source) === true) //if this is a file then zip it
{
$zip->addFromString(basename($source), file_get_contents($source));
unlink($source)
}

PHP : realpath , difference between windows and unix paths

I know that there is a difference between the result of the function realpath between windows and unix paths
I have this function for create a zip , and i don't know how to convert it to work both on windows and unix (for now only works on unix)
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->addFromString(str_replace($source . '/', '', $file), file_get_contents($file));
}
}
}else if (is_file($source) === true){
$zip->addFromString(basename($source), file_get_contents($source));
}
return $zip->close();
}
I think DIRECTORY_SEPARATOR constant can help the conversion
UPDATE
this works on windows and unix
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;
if (is_dir($file) === true)
{
$zip->addEmptyDir(str_replace($source . '/', '', $file));
}
else if (is_file($file) === true)
{
$str1 = str_replace($source . '/', '', '/'.$file);
$zip->addFromString($str1, file_get_contents($file));
}
}
}
else if (is_file($source) === true)
{
$zip->addFromString(basename($source), file_get_contents($source));
}
return $zip->close();
}

zip main folder with sub folder inside

I have a folder with some files and sub folder inside. How im going to read the directory and zip the main folder?
Ex:
maindirectory
--- file 1
--- file 2
--- subdirectory 1
------ file 3
------ file 4
--- subdirectory 2
------ file 5
------ file 6
I'm using this script:
function Zip($source, $destination, $include_dir = false)
{
if (!extension_loaded('zip') || !file_exists($source)) {
return false;
}
if (file_exists($destination)) {
unlink ($destination);
}
$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_CHILD);
if ($include_dir) {
$arr = explode("/",$source);
$maindir = $arr[count($arr)- 1];
$source = "";
for ($i=0; $i < count($arr) - 1; $i++) {
$source .= '/' . $arr[$i];
}
$source = substr($source, 1);
$zip->addEmptyDir($maindir);
}
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->addFromString(str_replace($source . '/', '', $file), file_get_contents($file));
}
}
}
else if (is_file($source) === true)
{
$zip->addFromString(basename($source), file_get_contents($source));
}
return $zip->close();
}
and I call the function like this:
Zip('image/data/','aaa.zip',false);
But what I get is it zip the whole C: folder. What I want is to only zip document inside the image/data/ folder.
How can I format the correct directory and it's subdirectories?
try this.
zipFile('image/data/','aaa.zip', true);
/**
* function zipFile. Creates a zip file from source to destination
*
* #param string $source Source path for zip
* #param string $destination Destination path for zip
* #param string|boolean $flag OPTIONAL If true includes the folder also
* #return boolean
*/
function zipFile($source, $destination, $flag = '')
{
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($flag)
{
$flag = basename($source) . '/';
//$zip->addEmptyDir(basename($source) . '/');
}
if (is_dir($source) === true)
{
$files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($source), RecursiveIteratorIterator::SELF_FIRST);
foreach ($files as $file)
{
$file = str_replace('\\', '/', realpath($file));
if (is_dir($file) === true)
{
$zip->addEmptyDir(str_replace($source . '/', '', $flag.$file . '/'));
}
else if (is_file($file) === true)
{
$zip->addFromString(str_replace($source . '/', '', $flag.$file), file_get_contents($file));
}
}
}
else if (is_file($source) === true)
{
$zip->addFromString($flag.basename($source), file_get_contents($source));
}
return $zip->close();
}
I edited the above code since I wasn't able to add empty folders and to avoid the C: drive as well
$otpt = "C:/xampp/htdocs/restricted/abc.zip";
$inpt = "C:/xampp/htdocs/Test/";
zipFile($inpt,$otpt, true); //Call to function
function zipFile($source, $destination, $flag = '')
{
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($flag)
{
$flag = basename($source) . '/';
}
if (is_dir($source) === true)
{
$files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($source), RecursiveIteratorIterator::SELF_FIRST);
foreach ($files as $file)
{
$file = str_replace('\\', '/', realpath($file));
if (strpos($flag.$file,$source) !== false) { // this will add only the folder we want to add in zip
if (is_dir($file) === true)
{
$zip->addEmptyDir(str_replace($source . '/', '', $flag.$file . '/'));
}
else if (is_file($file) === true)
{
$zip->addFromString(str_replace($source . '/', '', $flag.$file), file_get_contents($file));
}
}
}
}
else if (is_file($source) === true)
{
$zip->addFromString($flag.basename($source), file_get_contents($source));
}
return $zip->close();
}
Thanks guys...i figure out the problem alr...
if (is_dir($source) === true)
{
$files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($source), RecursiveIteratorIterator::SELF_FIRST);
foreach ($files as $file)
{
$file = str_replace('\\', '/', realpath($file));
if (is_dir($file) === true)
{
//$zip->addEmptyDir(str_replace($source . '/', '', $flag.$file . '/')); //this should be commented so it wont include the main path
}
else if (is_file($file) === true)
{
$zip->addFromString(str_replace($source . '/', '', $flag.$file), file_get_contents($file));
}
}
}
1- You should put all these code in a function
function readfile($source){
if (is_dir($source) === true) {
$files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($source), RecursiveIteratorIterator::SELF_FIRST);
foreach ($files as $file)
{
$file = str_replace('\\', '/', realpath($file));
if (is_dir($file) === true)
{
$zip->addEmptyDir(str_replace($source . '/', '', $flag.$file . '/'));
}
else if (is_file($file) === true)
{
$zip->addFromString(str_replace($source . '/', '', $flag.$file), file_get_contents($file));
}
}
}
else if (is_file($source) === true)
{
$zip->addFromString($flag.basename($source), file_get_contents($source));
}
// here you would use recursive function
else if (is_dir($source) === true)
{
readfile($source);
}
}
summary :
if you find a file then you would do operation which you want and if you find a directory the you would use recursive function for traversing directory more.
You should add:
if(basename($file) === '.' || basename($file) === '..'){
continue;
}
like this:
if (is_dir($source) === true) {
$files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($source), RecursiveIteratorIterator::SELF_FIRST);
foreach ($files as $file) {
if(basename($file) === '.' || basename($file) === '..'){
continue;
}
$file = str_replace('\\', '/', realpath($file));
if (is_dir($file) === true) {
$zip->addEmptyDir(str_replace($source . '/', '', $flag.$file . '/'));
} else if (is_file($file) === true) {
$zip->addFromString(str_replace($source . '/', '', $flag.$file), file_get_contents($file));
}
}
} else if (is_file($source) === true) {
$zip->addFromString($flag.basename($source), file_get_contents($source));
}
It will be simpler and if you use the addfile method instead of addfromstring
for win
public function ArchiveFile($path)
{
$path=realpath($path);
$zip = new \ZipArchive();
$path= str_replace('/','\\', $path );
$nameFile = $path.'\\'.'letter'.time().'.zip';
if ($zip->open($nameFile,\ZipArchive::CREATE)===TRUE){
if (is_dir($path))
{
$pathSource= $path. '\\';
$directory = new \RecursiveDirectoryIterator($path);
$files = new \RecursiveIteratorIterator($directory, \RecursiveIteratorIterator::SELF_FIRST );
}
foreach ($files as $name=>$file)
{
if (in_array(substr($name, strrpos($name,'\\')+1), array('.','..')))
{
continue;
}
if (is_file($name)===TRUE) {
$zip->addFile($name, str_replace($pathSource, "", $name));
}
}
$zip->close();
rename($nameFile, $nameFile.'.xlsx');

Recursively zip multiple folders

The following function works great, but it only zips the 1 folder. I need to zip several specific folders in the root of a site but not all of the rest.
Source: How to [recursively] Zip a directory in PHP?
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('\\', '/', realpath($file));
if (is_dir($file) === true)
{
$zip->addEmptyDir(str_replace($source . '/', '', $file . '/'));
}
else if (is_file($file) === true)
{
$zip->addFromString(str_replace($source . '/', '', $file), file_get_contents($file));
}
}
}
else if (is_file($source) === true)
{
$zip->addFromString(basename($source), file_get_contents($source));
}
return $zip->close();
Called with this:
Zip('/folder/to/compress/', './compressed.zip');
If I understand you correctly, you can simply change your code to expect $source to be either string or array. Then you can loop through that array and add all desired folders and their sub-folders
Examples:
function Zip($source, $destination)
{
if (is_string($source)) $source_arr = array($source); // convert it to array
if (!extension_loaded('zip')) {
return false;
}
$zip = new ZipArchive();
if (!$zip->open($destination, ZIPARCHIVE::CREATE)) {
return false;
}
foreach ($source_arr as $source)
{
if (!file_exists($source)) continue;
$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('\\', '/', realpath($file));
if (is_dir($file) === true)
{
$zip->addEmptyDir(str_replace($source . '/', '', $file . '/'));
}
else if (is_file($file) === true)
{
$zip->addFromString(str_replace($source . '/', '', $file), file_get_contents($file));
}
}
}
else if (is_file($source) === true)
{
$zip->addFromString(basename($source), file_get_contents($source));
}
}
return $zip->close();
}
Zip might be empty of all specified paths are invalid but you can take care of that too.

Categories