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($zdata, 0, strlen($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', 0 );
$cdrec .= pack('v', 0 );
$cdrec .= pack('v', 0 );
$cdrec .= pack('v', 0 );
$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!!