Ho trovato questa "semplice" libreria per creare ZIP:


Codice PHP:
class zipfile
{
    var 
$datasec      = array();
var 
$ctrl_dir     = array();
var 
$eof_ctrl_dir "\x50\x4b\x05\x06\x00\x00\x00\x00";
var 
$old_offset   0;

function 
unix2DosTime($unixtime 0) {
        
$timearray = ($unixtime == 0) ? getdate() : getdate($unixtime);

        if (
$timearray['year'] < 1980) {
            
$timearray['year']    = 1980;
            
$timearray['mon']     = 1;
            
$timearray['mday']    = 1;
            
$timearray['hours']   = 0;
            
$timearray['minutes'] = 0;
            
$timearray['seconds'] = 0;
        } 
// end if

        
return (($timearray['year'] - 1980) << 25) | ($timearray['mon'] << 21) | ($timearray['mday'] << 16) |
                (
$timearray['hours'] << 11) | ($timearray['minutes'] << 5) | ($timearray['seconds'] >> 1);
    } 
// end of the 'unix2DosTime()' method

    
function addFile($data$name$time 0)
    {
        
$name     str_replace('\\''/'$name);

$dtime    dechex($this->unix2DosTime($time));
        
$hexdtime '\x' $dtime[6] . $dtime[7]
                  . 
'\x' $dtime[4] . $dtime[5]
                  . 
'\x' $dtime[2] . $dtime[3]
                  . 
'\x' $dtime[0] . $dtime[1];
        eval(
'$hexdtime = "' $hexdtime '";');

        
$fr   "\x50\x4b\x03\x04";
        
$fr   .= "\x14\x00";            // ver needed to extract
        
$fr   .= "\x00\x00";            // gen purpose bit flag
        
$fr   .= "\x08\x00";            // compression method
        
$fr   .= $hexdtime;             // last mod time and date

        // "local file header" segment
        
$unc_len strlen($data);
        
$crc     crc32($data);
        
$zdata   gzcompress($data);
        
$zdata   substr(substr($zdata0strlen($zdata) - 4), 2); // fix crc bug
        
$c_len   strlen($zdata);
        
$fr      .= pack('V'$crc);             // crc32
        
$fr      .= pack('V'$c_len);           // compressed filesize
        
$fr      .= pack('V'$unc_len);         // uncompressed filesize
        
$fr      .= pack('v'strlen($name));    // length of filename
        
$fr      .= pack('v'0);                // extra field length
        
$fr      .= $name;

        
// "file data" segment
        
$fr .= $zdata;

        
// "data descriptor" segment (optional but necessary if archive is not
        // served as file)
        
$fr .= pack('V'$crc);                 // crc32
        
$fr .= pack('V'$c_len);               // compressed filesize
        
$fr .= pack('V'$unc_len);             // uncompressed filesize

        // add this entry to array
        
$this -> datasec[] = $fr;

        
// now add to central directory record
        
$cdrec "\x50\x4b\x01\x02";
        
$cdrec .= "\x00\x00";                
        
$cdrec .= "\x14\x00";                
        
$cdrec .= "\x00\x00";                
        
$cdrec .= "\x08\x00";                
        
$cdrec .= $hexdtime;                 
        
$cdrec .= pack('V'$crc);           
        
$cdrec .= pack('V'$c_len);         
        
$cdrec .= pack('V'$unc_len);       
        
$cdrec .= pack('v'strlen($name) ); 
        
$cdrec .= pack('v');             
        
$cdrec .= pack('v');             
        
$cdrec .= pack('v');             
        
$cdrec .= pack('v');             
        
$cdrec .= pack('V'32 );            

        
$cdrec .= pack('V'$this -> old_offset ); 
        
$this -> old_offset += strlen($fr);

        
$cdrec .= $name;
        
$this -> ctrl_dir[] = $cdrec;

    } 
// end of the 'addFile()' method

    
    
function file()
    {
        
$data    implode(''$this -> datasec);
        
$ctrldir implode(''$this -> ctrl_dir);


        return
            
$data .
            
$ctrldir .
            
$this -> eof_ctrl_dir .
            
pack('v'sizeof($this -> ctrl_dir)) . 
            
pack('v'sizeof($this -> ctrl_dir)) .  
            
pack('V'strlen($ctrldir)) .           
            
pack('V'strlen($data)) .              
            
"\x00\x00";                             
    } 
// end of the 'file()' method


// end of the 'zipfile' class 



Più questa funzione che "aggiunge" una directory al mio archivio:


Codice PHP:
function add_dir($dir,$newzip)    # recursive adding of files to zip
{
static 
$no;
$no=$no+1;
if((
$no>10)|| (strlen($newzip->file())>5000000)) die("Too many sub directories (>$no) or Total size > 5MB!<br>Try them by parts. [Some security measures!] ");
if(
$dh opendir($dir)) 
  {
  
$newzip->addFile("","$dir/",0);
  while ((
$file readdir($dh)))  {$files[] = $file;}


  foreach(
$files as $file)
   {
    if(
$file!="."&&$file!=".."&&!is_dir("$dir/$file")&&is_readable("$dir/$file"))
    {
    
$data=file_get_contents("$dir/$file");
    
$newzip->addFile($data,"$dir/$file",0);
    }
   }
  foreach(
$files as $file)
   {
   if(
$file!="."&&$file!=".."&&is_dir("$dir/$file"))
    {
    
add_dir("$dir/$file",$newzip);
    }
   }
 
closedir($dh);
  }




Quindi, in questo modo, posso creare un archivio ZIP "al volo", inserendovi una cartella "mydir":


Codice PHP:
include_once("zip.lib.php");

$myroot='/myroot/';
$mydir='mydir';

$newzip = new zipfile();
chdir($myroot);

add_dir($mydir,$newzip);

header("Content-Disposition: attachment; filename=".$mydir.".zip");
header("Content-Type: file/x-msdownload");
$data=$newzip->file();
header("Content-Length: ".strlen($data));
echo 
$data



Il problema è che, creando un archivio "grande", si incappa nel solito errore "MEMORY LIMIT EXCEED" ....


  • Come potrei aggirare il problema??
  • Si potrebbe modificare il metodo "file()" della classe "zipfile", in modo da spezzare i dati in parti più piccole??
  • Oppure fare un output "poco alla volta", quando faccio "echo $data", alla fine del mio codice??
  • Altre soluzioni??


Grazie!!