A finales del 2016 me vi una situación en la que generar un archivo comprimido de una carpeta particular de un hosting al que solo tenía acceso por FTP me daba por resultado una operación de descarga de copias más eficiente por la velocidad de descarga que se tenía.
Buscando por la red encontré una función PHP y ejemplo de su uso en este enlace:
http://blog.kiuvox.com/comprimir-un-directorio-completo-en-zip-desde-php/
Esa función de Hug0 (así aparece el nombre del autor de la función PHP que mencioné) efectúa la compresión de todos los archivos de la carpeta que se envía como parámetro.
Resultó que lo que yo necesitaba la descarga del contenido de una carpeta exceptuando algunos archivos y algunas sub-carpetas, entonces esa función la metí en una clase y nació [ cl_zipFile ].
<?php class cl_zipFile { private $pathToStart = ''; var $pfn = ''; var $path = ''; var $fileName= ''; var $folderToExclude = NULL; var $emptyFolderToAdd = NULL; var $explicitFileToExclude = NULL; var $nFiles = 0; var $maxNFiles = 0; var $includeEmptyFolders = true; function addEmptyFolderToAdd($path) { $this->emptyFolderToAdd[$path] = ''; } function addFolderToExclude($path) { $this->folderToExclude[$path] = ''; } function addExplicitFileToExclude($pfn) { $this->explicitFileToExclude[$pfn] = ''; } function addToZip($path, $zip) { if ($this->nFiles >= $this->maxNFiles && $this->maxNFiles != 0) return; if ( $this->includeEmptyFolders && !( $this->folderToExclude == NULL ? false : isset($this->folderToExclude[$path]) ) ) { $xpath = str_replace($this->pathToStart, '', $path); if ($xpath != '') $zip->addEmptyDir($xpath); } if (is_dir($path)) { if ($xDir = opendir($path)) { while (($item = readdir($xDir)) !== false) { if ($item != "." && $item != "..") { if (is_dir($path . $item)) { if (!($this->folderToExclude == NULL ? false : isset($this->folderToExclude[$path . $item]) ) ) $this->addToZip($path . $item . "/", $zip); } elseif (is_file($path . $item)) { if ( $this->explicitFileToExclude == NULL ? true : !isset( $this->explicitFileToExclude[$path . $item ] ) ) { $this->nFiles++; if ($this->nFiles > $this->maxNFiles && $this->maxNFiles != 0) break; $zip->addFile($path . $item, str_replace($this->pathToStart, '', $path) . $item); } } } } closedir($xDir); } } } function createZipFromFolder($pathToStart, $targetPath, $targetFileName) { $this->pfn = ''; $this->pathToStart = $pathToStart; $zip = new ZipArchive(); if(!file_exists($targetPath)) mkdir($targetPath); if ($zip->open($targetFileName, ZIPARCHIVE::CREATE) === true) { $this->addToZip($pathToStart, $zip); if ($this->emptyFolderToAdd != NULL) foreach($this->emptyFolderToAdd as $a => $b) $zip->addEmptyDir($a); $zip->close(); rename($targetFileName, $targetPath . '/' . $targetFileName); if (file_exists($targetPath. "/" . $targetFileName)) { $this->path = $targetPath; $this->fileName = $targetFileName; $this->pfn = $targetPath . '/' . $targetFileName; return true; } else return false; } else return false; } } ?>
<?php /* En caso de que la cantidad/peso de archivos a procesar sea un valor elevado se deberá modificar el tiempo límite de ejecución de este programa. [ set_time_limit ] cambia el tiempo límite a la cantidad de segundos que reciba. Si se le envía valor 0 el tiempo límite queda como ilimitado */ // Tiempo límite: 5 minutos: set_time_limit(5 * 60); // Para el ejemplo se utilizará la carpeta "files-demo" $path = 'files-demo'; // Creación de carpeta "files-demo" y unas cuantas subcarpetas // y archivos para este ejemplo if (!file_exists($path)) { $ar = array( $path, $path . '/001', $path . '/002', $path . '/003', $path . '/002/001', $path . '/002/002', $path . '/no-agregar' ); for ($i = 0; $i < count($ar); $i++) { mkdir($ar[$i]); file_put_contents($ar[$i]. '/a.txt', date('Y-m-d H:i:s')); // file_put_contents($ar[$i] . '/b.txt', date('Y-m-d H:i:s')); // file_put_contents($ar[$i] . '/c.txt', date('Y-m-d H:i:s')); } } // Instancia de clase cl_zipFile y asignación de cantidad máxima // de archivos como ilimitada. $o = new cl_zipFile(); $o->maxNFiles = 0; // Se agrega como carpeta a no agregar a la llamada "no-agregar" $o->addFolderToExclude($path . '/no-agregar'); // Se agrega como archivos a no incluir a estos: $o->addExplicitFileToExclude($path . '/002/001/a.txt'); // Se agrega un par de carpeta vacías a agregar en el zip $o->addEmptyFolderToAdd('ROOT-EMPTY-FOLDER-ADDED'); $o->addEmptyFolderToAdd('002/EMPTY-FOLDER-IN-002-ADDED'); // Se genera el archivo zip $zipName = date('Ymd-His') . '.zip'; $zipTargetFolder = 'zipFiles'; $ok = $o->createZipFromFolder( $path . '/', // Ruta de folder a procesar $zipTargetFolder, // Carpeta destino del zip $zipName // Nombre del zip ); // Se muestra enlace de descarga del ZIP if ($ok) echo 'ZIP generado: ' . '<a href="' . $zipTargetFolder . '/' . $zipName . '">' . $zipName . '</a>'; else // O anuncio de que se ha tenido algún problema echo 'Problemas al intentar generar el zip.'; ?>