Programación

PHP

Generación de zip de archivos de una carpeta

Última actualización: 18-11-2017 17:43

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 ].

Clase PHP cl_zipFile

La clase tiene métodos para agregar listas de: También tiene este par de propiedades: La función createZipFromFolder que genera un ZIP de una carpeta recibe estos parámetros:
<?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;
        }
    }
 
?>

Ejemplo de uso

El código PHP del ejemplo que se está publicando ejecuta estos pasos:
Contenido de la carpeta a comprimir del ejemplo
  • files-demo
    • 001
      • a.txt
    • 002
      • 001
        • a.txt
      • 002
        • a.txt
      • a.txt
    • 003
      • a.txt
    • no-agregar
      • a.txt
    • a.txt
Contenido del archivo ZIP resultante
  • [ ARCHIVO ZIP ]
    • 001
      • a.txt
    • 002
      • 001
      • 002
        • a.txt
      • EMPTY-FOLDER-IN-002-ADDED
      • a.txt
    • 003
      • a.txt
    • ROOT-EMPTY-FOLDER-ADDED
    • a.txt
Se ha marcado naranja la carpeta de la que se excluyó un archivo y que se ha agregado vacía al zip por el valor de la propiedad includeEmptyFolders.

 

Código de ejemplo de uso
<?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.';
?>

 

Política de Privacidad

Última actualización: 23 de diciembre de 2024

 X 

Tu privacidad es importante para nosotros. En esta política de privacidad, explicamos qué información recopilamos cuando visitas nuestro sitio web y cómo utilizamos esa información.

1. Información que recopilamos

Este sitio no recopila información personal de los usuarios, excepto cuando un usuario elige voluntariamente comunicarse a través del formulario de contacto. En ese caso, los datos proporcionados (como tu nombre y correo electrónico) se utilizarán únicamente para responder a tu consulta.

2. Uso de Cookies

Este sitio web utiliza una única cookie esencial llamada PHPSESSID.

No usamos cookies de análisis ni de seguimiento.

3. Seguridad de los datos

Adoptamos medidas técnicas y organizativas razonables para proteger cualquier información que compartas con nosotros contra el acceso no autorizado, pérdida o alteración.

4. Enlaces a sitios de terceros

Nuestro sitio web puede contener enlaces a otros sitios web. No somos responsables de las prácticas de privacidad ni del contenido de dichos sitios.

5. Cambios en esta política de privacidad

Nos reservamos el derecho de actualizar esta política de privacidad en cualquier momento. Cualquier cambio será publicado en esta misma página e incluirá la fecha de la última actualización.

6. Contacto

Si tienes preguntas o inquietudes sobre esta política de privacidad, puedes comunicarte con nosotros a través de la página de contacto disponible en este sitio web.

7. Cumplimiento con Normativas Internacionales de Privacidad

Nuestro sitio web cumple con las principales regulaciones internacionales de protección de datos personales para garantizar la privacidad y seguridad de los usuarios. Esto incluye, pero no se limita a, las siguientes leyes:

Si tienes preguntas o dudas sobre el cumplimiento de estas leyes, no dudes en ponerte en contacto conmigo a través de la página de contacto de este sitio web.