0

I am currently working on a tool made with PHP (quite newbie with this technology...) which should generate zip files with a set of files inside. This set of files can be:

  • Basic files (mutliple formats)
  • Full directories (will be added into the resulting zip as a new zipped file - ZIP inside the final ZIP)

The thing is that when the zip files contains simple files it is downloaded properly but when the file contains the "Full directory zip file" then the resulting ZIP file get corrupted...

Below the code I am currently using (sorry if its a bit messy but is the first time I work with PHP...)

function ZipFiles($fileArr,$id) {
    $destination = "{$_SERVER['DOCUMENT_ROOT']}/wmdmngtools/tempFiles/WMDConfigFiles_".$id.".zip";
    $valid_files = array();

    //if files were passed in...
    if(is_array($fileArr)) {
        //cycle through each file
        foreach($fileArr as $file) {            

            if(is_dir($file)) {
                //If path is a folder we zip it and put it on $valid_files[]
                $resultingZipPath = "{$_SERVER['DOCUMENT_ROOT']}/wmdmngtools/tempFiles/".basename($file)."_FOLDER.zip";
                ZipFolder($file,$resultingZipPath );
                $valid_files[] = $resultingZipPath ;    
            }
            else {              
                //If path is not a folder then we make sure the file exists
                if(file_exists("{$_SERVER['DOCUMENT_ROOT']}/wmdmngtools/tempFiles/".$file)) {
                    $valid_files[] = $file;                 
                }
            }
        }
    }
    //if we have good files...
    if(count($valid_files)) {
        //create the archive
        $zip = new ZipArchive();
        if($zip->open($destination,ZIPARCHIVE::CREATE) !== true) {
            return false;
        }
        //add the files
        foreach($valid_files as $file) {
            $zip->addFile("{$_SERVER['DOCUMENT_ROOT']}/wmdmngtools/tempFiles/".$file,$file);
        }

        $zip->close();

        return $destination;
    }
    else
    {
        return "";
    }
}

function ZipFolder($source, $destination) {

    // Initialize archive object
    $folderZip = new ZipArchive();
    $folderZip->open($destination, ZipArchive::CREATE | ZipArchive::OVERWRITE);

    // Create recursive directory iterator
    /** @var SplFileInfo[] $files */
    $files = new RecursiveIteratorIterator(
        new RecursiveDirectoryIterator($source),
        RecursiveIteratorIterator::LEAVES_ONLY
    );

    foreach ($files as $name => $file)
    {
        // Skip directories (they would be added automatically)
        if (!$file->isDir())
        {
            // Get real and relative path for current file
            $filePath = $file->getRealPath();
            $relativePath = substr($filePath, strlen($source) + 1);

            // Add current file to archive
            $folderZip->addFile($filePath, $relativePath);
        }
    }

    // Zip archive will be created only after closing object
    $folderZip->close();

}

On it we can see two functions:

  • ZipFiles: is the main fucntion that is called by passing a list/array (contains the list of files and folders that will be added into the final ZIP) and an ID parameter which is simply used for generatig different file names... (can be ignored)
  • ZipFolder: this fucntion is called for each of the folders (not files) on the above mentioned list/array in order to zip that folder and create a zip file to add it on the final file. (based on what I found in How to zip a whole folder using PHP)

I have tried many things like mentioned in above post like closing all files, or avoiding empty zips inside the zip but nothing worked...

Zip inside zip (php)

Maybe I missed something (most probably :) ) but am running out of aces so any help/guideance would be appreciated.

In case more info is needed please let me know and will post it.

Thanks a lot in advance!!

Community
  • 1
  • 1
byle.05
  • 194
  • 2
  • 16

1 Answers1

1

Finally found the issue. Seems that the file was generated properly but when downloading it from PHP there was a problem when size was bigger than a concrete number. THis was due to wrong definition of the message length on the header definition:

header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Length: ".filesize($zippedFile));
header("Content-Disposition: attachment; filename=".$zippedFile);   
header("Content-type: application/zip");
header("Content-Transfer-Encoding: binary");

Even if I guess it may not be a correct practice I removed the Content-Length entry and now I get the correct file despite of its size.

byle.05
  • 194
  • 2
  • 16