This article provides a detailed analysis of how php generates zip files. For more information, see
The code is as follows:
Require_once "./include/zip. php ";
$ Zip = new PHPZip ();
// $ Zip-> createZip ("directory address of the folder to be compressed", "file name .zip"); // only generate files that are not automatically downloaded
$ Zip-> downloadZip ("directory address of the folder to be compressed", "file name .zip"); // automatically download
Example: You can refer to the following pseudocode to see a specific use case:
Code
The code is as follows:
Require_once "./include/zip. php ";
If (! $ Download ){
Exit ();
}
Set_time_limit (60 );
$ TmpManager = new TmpManager (); // assume that we have a class to complete subsequent operations.
$ Tempfolder = array ();
$ Tempfile = array ();
// Suppose we download the selected folder or file by selecting checkbox on the page and package it together
For ($ I = 0; $ I <$ checkboxnum; $ I ++ ){
$ Value =$ {"select". $ I };
If ($ value! = ''){
$ This_type = substr ($ value, 0, 1 );
$ This_id = substr ($ value, 1 );
// Separate folders and files
If ($ this_type = 'd '){
$ Tempfolder [] = $ this_id;
}
Elseif ($ this_type = 'F '){
$ Tempfile [] = $ this_id;
}
}
}
@ Mkdir ($ tempdir );
$ Curtempdir = "$ tempdir/". $ userid; // different users operate in different temporary folders
If (file_exists ($ curtempdir )){
$ TmpManager-> DeleteDir ($ curtempdir); // delete the old folder
}
If (sizeof ($ tempfolder)> 0 | sizeof ($ tempfile)> 0 ){
Mkdir ($ curtempdir, 0777); // re-create a folder if there is a folder for packaging objects
}
If (sizeof ($ tempfile)> 0 ){
$ TmpManager-> CopyFile ($ tempfile, $ curtempdir); // copy the file to be downloaded to the created folder.
}
If (sizeof ($ tempfolder)> 0 ){
$ TmpManager-> CopyFolder ($ tempfolder, $ curtempdir); // copy the folder to be downloaded to the created folder
}
$ Zip = new PHPZip ();
$ Zip-> downloadZip ($ curtempdir, "file _". date ('ymmd'). ". zip"); // package and download
Zip. php
The code is as follows:
/*
File name:/include/zip. php
Author: hsf-e 2009/04/15
*/
Class PHPZip {
Var $ dirInfo = array ("0", "0 ");
Var $ rootDir = '';
Var $ datasec = array ();
Var $ ctrl_dir = array ();
Var $ eof_ctrl_dir = "/x50/x4b/x05/x06/x00/x00/x00/x00 ";
Var $ old_offset = 0;
Function downloadZip (){
CreateZip ($ dir, $ zipfilename, true );
}
Function createZip ($ dir, $ zipfilename, $ autoDownload = false ){
If (@ function_exists ('gzcompress ')){
@ Set_time_limit ("0 ");
If (is_array ($ dir )){
$ Fd = fopen ($ dir, "r ");
$ FileValue = fread ($ fd, filesize ($ filename ));
Fclose ($ fd );
If (is_array ($ dir) $ filename = basename ($ dir );
$ This-> addFile ($ fileValue, "$ filename ");
} Else {
$ This-> dirTree ($ dir, $ dir );
}
$ Zipfilenametemp = time (). $ zipfilename;
$ Out = $ this-> filezip ();
$ Fp = fopen ($ zipfilenametemp, "w ");
Fwrite ($ fp, $ out, strlen ($ out ));
Fclose ($ fp );
$ Filesize = filesize ($ zipfilenametemp );
If ($ filesize <104857600 ){
If ($ autoDownload ){
Header ("Content-type: application/octet-stream ");
Header ("Content-disposition: attachment; filename =". $ zipfilename );
}
Echo $ this-> filezip ();
} Else {
Echo "create zip error! ";
}
Unlink ($ zipfilenametemp );
}
}
// Get dir tree ..
Function dirTree ($ directory, $ rootDir ){
Global $ _ SERVER, $ dirInfo, $ rootDir;
$ FileDir = $ rootDir;
$ MyDir = dir ($ directory );
While ($ file = $ myDir-> read ()){
If (is_dir ("$ directory/$ file") and $ file! = "." And $ file! = ".."){
$ DirInfo [0] ++;
$ RootDir = "$ fileDir $ file /";
$ This-> addFile (''," $ rootDir ");
// Go on n's folders
$ This-> dirTree ("$ directory/$ file", $ rootDir );
} Else {
If ($ file! = "." And $ file! = ".."){
$ DirInfo [1] ++;
// $ Fd = fopen ("$ directory/$ file", "r ");
$ FileValue = file_get_contents ("$ directory/$ file ");
// Fclose ($ fd );
$ This-> addFile ($ fileValue, "$ fileDir $ file ");
}
}
}
$ MyDir-> close ();
}
Function unix2DosTime ($ unixtime = 0 ){
$ Timearray = ($ unixtime = 0 )? Getdate (): getdate ($ unixtime );
If ($ timearray ['Year'] <1980 ){
$ Timearray ['Year'] = 1980;
$ Timearray ['mon'] = 1;
$ Timearray ['mday'] = 1;
$ Timearray ['urs'] = 0;
$ Timearray ['minutes '] = 0;
$ Timearray ['seconds'] = 0;
} // End if
Return ($ timearray ['Year']-1980) <25) | ($ timearray ['mon'] <21) | ($ timearray ['mday'] <16) |
($ Timearray ['urs'] <11) | ($ timearray ['minutes '] <5) | ($ timearray ['seconds']> 1 );
}
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 );
$ C_len = strlen ($ zdata );
$ Zdata = substr ($ zdata, 0, strlen ($ zdata)-4), 2); // fix the crc bug
$ 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;
$ New_offset = strlen (implode ('', $ this-> datasec ));
// Now add to central directory record
$ Cdrec = "/x50/x4b/x01/x02 ";
$ Cdrec. = "/x00/x00"; // version made
$ Cdrec. = "/x14/x00"; // version needed to extract
$ Cdrec. = "/x00/x00"; // gen purpose bit flag
$ Cdrec. = "/x08/x00"; // compression method
$ Cdrec. = $ hexdtime; // last mod time & date
$ Cdrec. = pack ('v', $ crc); // crc32
$ Cdrec. = pack ('v', $ c_len); // compressed filesize
$ Cdrec. = pack ('v', $ unc_len); // uncompressed filesize
$ Cdrec. = pack ('v', strlen ($ name); // length of filename
$ Cdrec. = pack ('v', 0); // extra field length
$ Cdrec. = pack ('v', 0); // file comment length
$ Cdrec. = pack ('v', 0); // disk number start
$ Cdrec. = pack ('v', 0); // internal file attributes
$ Cdrec. = pack ('v', 32); // external file attributes-'archive' bit set
$ Cdrec. = pack ('v', $ this-> old_offset); // relative offset of local header
$ This-> old_offset = $ new_offset;
$ Cdrec. = $ name;
// Optional extra field, file comment goes here
// Save to central directory
$ This-> ctrl_dir [] = $ cdrec;
}
Function filezip (){
$ Data = implode ('', $ this-> datasec );
$ Ctrldir = implode ('', $ this-> ctrl_dir );
Return
$ Data.
$ Ctrldir.
$ This-> eof_ctrl_dir.
Pack ('v', sizeof ($ this-> ctrl_dir). // total # of entries "on this disk"
Pack ('v', sizeof ($ this-> ctrl_dir). // total # of entries overall
Pack ('v', strlen ($ ctrldir). // size of central dir
Pack ('v', strlen ($ data). // offset to start of central dir
"/X00/x00"; //. zip file comment length
}
}
?>