CnV
CnV

Reputation: 391

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?

Upvotes: 6

Views: 9036

Answers (6)

user3035145
user3035145

Reputation: 33

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');

Upvotes: 0

Adam
Adam

Reputation: 27

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));
}

Upvotes: 0

steven leitao
steven leitao

Reputation: 31

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();
}

Upvotes: 3

Sajid Ali Khan
Sajid Ali Khan

Reputation: 11

       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.

Upvotes: 0

ARIF MAHMUD RANA
ARIF MAHMUD RANA

Reputation: 5166

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();
}

Upvotes: 7

CnV
CnV

Reputation: 391

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));
        }
    }
}

Upvotes: 1

Related Questions