Maison > Article > développement back-end > ZIP处理---H_zip.php
1 <?php 2 /************************************* 3 * ZIP处理---H_zip.php 4 * 创建人: huang_xiang 5 * 创建时间:2008-12-25 9:29 6 * 更新时间:2009-2-18 13:37 7 * Email:yin273642232@163.com QQ:273642232 8 *************************************/ 9 /************************************* 10 实例代码 11 include_once("H_zip.php"); //引入文件 12 $H_zip = new H_zip(); //产生对象 13 $H_zip -> get_List($zip_name); //返回:返回获取zip文件和文件夹列表,参数:$zip_name-zip文件名称;'; 14 $H_zip -> Extract($zn,$to); //返回:解压zip,参数:$zn-zip文件名称:$to-解压到 15 $H_zip -> addfiles($H_file='test.zip',$H_flist); //返回:压缩zip,参数:$H_file-压缩zip文件名称:$Hfile-文件列表(array(array('1.txt','test.php'),array('1.txt','k/my.php'))) 16 17 $H_zip_file = 't/example.zip'; 18 $H_zip=new H_zip(); 19 print_r($H_zip->Extract($H_zip_file,'./',array(-1))); //解压 20 print_r($H_zip->get_List($H_zip_file)); //返回列表 21 $H_zip -> addfiles($H_file='test.zip',array(array('1.txt','test.php'),array('1.txt','k/my.php'))); //压缩 22 23 *************************************/ 24 //Start Class 25 class H_zip{ 26 public $datasec, $ctrl_dir = array(); 27 public $eof_ctrl_dir = "\x50\x4b\x05\x06\x00\x00\x00\x00"; 28 public $old_offset = 0; 29 public $dirs = Array("."); 30 public $H_temnm = ''; 31 32 public function __construct(){ 33 //当实例化一个对象的时候,这个对象的这个方法首先被调用 34 return ''; 35 } 36 public function __destruct(){ 37 //当删除一个对象或对象操作终止的时候,调用该方法 38 return ''; 39 } 40 public function __get($key){ 41 //当试图读取一个并不存在的属性的时候被调用 42 return '['.$key.'] Variable not find'; 43 } 44 public function __set($key,$val){ 45 //当试图向一个并不存在的属性写入值的时候被调用 46 return '['.$key.'] Variable not find'; 47 } 48 public function __call($key,$args){ 49 //当试图调用一个对象并不存在的方法时,调用该方法 50 return '['.$key.'] Function not find'; 51 } 52 public function __toString(){ 53 //当打印一个对象的时候被调用 54 return $this -> H_desce(); 55 } 56 public function __clone(){ 57 //当对象被克隆时,被调用 58 return "clone"; 59 } 60 public function H_desce(){ 61 //返回描述 62 $this -> H_desce .= '类名:H_zip-ZIP处理;'; 63 $this -> H_desce .= '函数:get_List($zip_name),返回:返回获取zip文件和文件夹列表,参数:$zip_name-zip文件名称;'; 64 $this -> H_desce .= '函数:Extract($zn,$to),返回:解压zip,参数:$zn-zip文件名称:$to-解压到;'; 65 $this -> H_desce .= '函数:addfiles($H_file="test.zip",$H_flist),返回:压缩zip,参数:$H_file-压缩zip文件名称:$Hfile-文件列表(array(array("1.txt","test.php"),array("1.txt","k/my.php")));'; 66 return $this -> H_desce; 67 } 68 69 public function get_List($zip_name){ 70 $zip = @fopen($zip_name, 'rb'); 71 if(!$zip) return(0); 72 $centd = $this -> ReadCentralDir($zip,$zip_name); 73 @rewind($zip); 74 @fseek($zip, $centd['offset']); 75 for ($i=0; $i<$centd['entries']; $i++){ 76 $header = $this -> ReadCentralFileHeaders($zip); 77 $header['index'] = $i;$info['filename'] = $header['filename']; 78 $info['stored_filename'] = $header['stored_filename']; 79 $info['size'] = $header['size']; 80 $info['compressed_size'] = $header['compressed_size']; 81 $info['crc'] = strtoupper(dechex( $header['crc'] )); 82 $info['mtime'] = $header['mtime']; 83 $info['comment'] = $header['comment']; 84 $info['folder'] = ($header['external']==0x41FF0010||$header['external']==16)?1:0; 85 $info['index'] = $header['index']; 86 $info['status'] = $header['status']; 87 $ret[]=$info; unset($header); 88 } 89 return $ret; 90 } 91 public function Add($files,$compact){ 92 if(!is_array($files[0])) $files = Array($files); 93 for($i=0;$files[$i];$i++){ 94 $fn = $files[$i]; 95 if(!in_Array(dirname($fn[0]),$this->dirs)) $this -> add_Dir(dirname($fn[0])); 96 if(basename($fn[0])) $ret[basename($fn[0])] = $this -> add_File($fn[1],$fn[0],$compact); 97 } 98 return $ret; 99 }100 public function get_file(){101 $data = implode('', $this -> datasec);102 $ctrldir = implode('', $this -> ctrl_dir);103 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";104 }105 public function add_dir($name){106 $name = str_replace("\\", "/", $name);107 $fr = "\x50\x4b\x03\x04\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00";108 $fr .= pack("V",0).pack("V",0).pack("V",0).pack("v", strlen($name));109 $fr .= pack("v", 0 ).$name.pack("V", 0).pack("V", 0).pack("V", 0);110 $this -> datasec[] = $fr;111 $new_offset = strlen(implode("", $this->datasec));112 $cdrec = "\x50\x4b\x01\x02\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00";113 $cdrec .= pack("V",0).pack("V",0).pack("V",0).pack("v", strlen($name));114 $cdrec .= pack("v", 0 ).pack("v", 0 ).pack("v", 0 ).pack("v", 0 );115 $ext = "\xff\xff\xff\xff";116 $cdrec .= pack("V", 16 ).pack("V", $this -> old_offset ).$name;117 $this -> ctrl_dir[] = $cdrec;118 $this -> old_offset = $new_offset;119 $this -> dirs[] = $name;120 }121 public function add_File($data, $name, $compact = 1){122 $name = str_replace('\\', '/', $name);123 $dtime = dechex($this->DosTime());124 $hexdtime = '\x'.$dtime[6].$dtime[7].'\x'.$dtime[4].$dtime[5].'\x'.$dtime[2].$dtime[3].'\x'.$dtime[0].$dtime[1];125 eval('$hexdtime = "'.$hexdtime.'";');126 if($compact) $fr = "\x50\x4b\x03\x04\x14\x00\x00\x00\x08\x00".$hexdtime;127 else $fr = "\x50\x4b\x03\x04\x0a\x00\x00\x00\x00\x00".$hexdtime;128 $unc_len = strlen($data);129 $crc = crc32($data);130 if($compact){131 $zdata = gzcompress($data);132 $c_len = strlen($zdata);133 $zdata = substr(substr($zdata, 0, strlen($zdata) - 4), 2);134 }else $zdata = $data;135 $c_len=strlen($zdata);136 $fr .= pack('V', $crc).pack('V', $c_len).pack('V', $unc_len);137 $fr .= pack('v', strlen($name)).pack('v', 0).$name.$zdata;138 $fr .= pack('V', $crc).pack('V', $c_len).pack('V', $unc_len);139 $this -> datasec[] = $fr;140 $new_offset = strlen(implode('', $this->datasec));141 if($compact) $cdrec = "\x50\x4b\x01\x02\x00\x00\x14\x00\x00\x00\x08\x00";142 else $cdrec = "\x50\x4b\x01\x02\x14\x00\x0a\x00\x00\x00\x00\x00";143 $cdrec .= $hexdtime.pack('V', $crc).pack('V', $c_len).pack('V', $unc_len);144 $cdrec .= pack('v', strlen($name) ).pack('v', 0 ).pack('v', 0 );145 $cdrec .= pack('v', 0 ).pack('v', 0 ).pack('V', 32 );146 $cdrec .= pack('V', $this -> old_offset );147 $this -> old_offset = $new_offset;148 $cdrec .= $name;149 $this -> ctrl_dir[] = $cdrec;150 return true;151 }152 public function DosTime(){153 $timearray = getdate();154 if($timearray['year'] < 1980){155 $timearray['year'] = 1980;156 $timearray['mon'] = 1;157 $timearray['mday'] = 1;158 $timearray['hours'] = 0;159 $timearray['minutes'] = 0;160 $timearray['seconds'] = 0;161 }162 return (($timearray['year'] - 1980) << 25) | ($timearray['mon'] << 21)|($timearray['mday'] << 16)|($timearray['hours'] << 11)|($timearray['minutes'] << 5)|($timearray['seconds'] >> 1);163 }164 public function Extract($zn, $to, $index = Array(-1)){165 $ok = 0;166 $zip = @fopen($zn,'rb');167 if(!$zip) return(-1);168 $cdir = $this->ReadCentralDir($zip,$zn);169 $pos_entry = $cdir['offset'];170 if(!is_array($index)) $index = array($index);171 for($i=0; $index[$i];$i++){172 if(intval($index[$i])!=$index[$i]||$index[$i]>$cdir['entries']) return(-1);173 }174 for ($i=0; $i<$cdir['entries']; $i++){175 @fseek($zip, $pos_entry);176 $header = $this->ReadCentralFileHeaders($zip);177 $header['index'] = $i; $pos_entry = ftell($zip);178 @rewind($zip);179 fseek($zip, $header['offset']);180 if(in_array("-1",$index)||in_array($i,$index)) $stat[$header['filename']]=$this->ExtractFile($header, $to, $zip);181 }182 fclose($zip);183 return $stat;184 }185 public function ReadFileHeader($zip){186 $binary_data = fread($zip, 30);187 $data = unpack('vchk/vid/vversion/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len', $binary_data);188 $header['filename'] = fread($zip, $data['filename_len']);189 if($data['extra_len'] != 0){190 $header['extra'] = fread($zip, $data['extra_len']);191 }else $header['extra'] = '';192 $header['compression'] = $data['compression'];193 $header['size'] = $data['size'];194 $header['compressed_size'] = $data['compressed_size'];195 $header['crc'] = $data['crc'];196 $header['flag'] = $data['flag'];197 $header['mdate'] = $data['mdate'];198 $header['mtime'] = $data['mtime'];199 if($header['mdate'] && $header['mtime']){200 $hour=($header['mtime']&0xF800)>>11;201 $minute=($header['mtime']&0x07E0)>>5;202 $seconde=($header['mtime']&0x001F)*2;203 $year=(($header['mdate']&0xFE00)>>9)+1980;204 $month=($header['mdate']&0x01E0)>>5;205 $day=$header['mdate']&0x001F;206 $header['mtime'] = mktime($hour, $minute, $seconde, $month, $day, $year);207 }else $header['mtime'] = time();208 $header['stored_filename'] = $header['filename'];209 $header['status'] = "ok";210 return $header;211 }212 public function ReadCentralFileHeaders($zip){213 $binary_data = fread($zip, 46);214 $header = unpack('vchkid/vid/vversion/vversion_extracted/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len/vcomment_len/vdisk/vinternal/Vexternal/Voffset', $binary_data);215 if($header['filename_len'] != 0) $header['filename'] = fread($zip,$header['filename_len']);216 else $header['filename'] = '';217 if($header['extra_len'] != 0) $header['extra'] = fread($zip, $header['extra_len']);218 else $header['extra'] = '';219 if($header['comment_len'] != 0) $header['comment'] = fread($zip, $header['comment_len']);220 else $header['comment'] = '';221 if($header['mdate'] && $header['mtime']){222 $hour = ($header['mtime'] & 0xF800) >> 11;223 $minute = ($header['mtime'] & 0x07E0) >> 5;224 $seconde = ($header['mtime'] & 0x001F)*2;225 $year = (($header['mdate'] & 0xFE00) >> 9) + 1980;226 $month = ($header['mdate'] & 0x01E0) >> 5;227 $day = $header['mdate'] & 0x001F;228 $header['mtime'] = mktime($hour, $minute, $seconde, $month, $day, $year);229 }else $header['mtime'] = time();230 $header['stored_filename'] = $header['filename'];231 $header['status'] = 'ok';232 if (substr($header['filename'], -1) == '/') $header['external'] = 0x41FF0010;233 return $header;234 }235 public function ReadCentralDir($zip,$zip_name){236 $size = filesize($zip_name);237 if($size < 277) $maximum_size = $size;238 else $maximum_size=277;239 @fseek($zip, $size-$maximum_size);240 $pos = ftell($zip); $bytes = 0x00000000;241 while ($pos < $size){242 $byte = @fread($zip, 1); $bytes=($bytes << 8) | Ord($byte);243 if($bytes == 0x504b0506){ $pos++; break; }244 $pos++;245 }246 $data=unpack('vdisk/vdisk_start/vdisk_entries/ventries/Vsize/Voffset/vcomment_size',fread($zip, 18));247 if($data['comment_size'] != 0) $centd['comment'] = fread($zip, $data['comment_size']);248 else $centd['comment'] = '';249 $centd['entries'] = $data['entries'];250 $centd['disk_entries'] = $data['disk_entries'];251 $centd['offset'] = $data['offset'];252 $centd['disk_start'] = $data['disk_start'];253 $centd['size'] = $data['size'];254 $centd['disk'] = $data['disk'];255 return $centd;256 }257 public function ExtractFile($header,$to,$zip){258 $header = $this->readfileheader($zip);259 if(substr($to,-1)!="/") $to.="/";260 if(!@is_dir($to)) @mkdir($to,0777);261 $pth = explode("/",dirname($header['filename']));262 for($i=0;isset($pth[$i]);$i++){263 if(!$pth[$i]) continue;264 if(!is_dir($to.$pth[$i])) @mkdir($to.$pth[$i],0777);265 }266 if(!($header['external']==0x41FF0010)&&!($header['external']==16)){267 if($header['compression']==0){268 $fp = @fopen($to.$header['filename'], 'wb');269 if(!$fp) return(-1);270 $size = $header['compressed_size'];271 while ($size != 0){272 $read_size = ($size < 2048 ? $size : 2048);273 $buffer = fread($zip, $read_size);274 $binary_data = pack('a'.$read_size, $buffer);275 @fwrite($fp, $binary_data, $read_size);276 $size -= $read_size;277 }278 fclose($fp);279 touch($to.$header['filename'], $header['mtime']);280 }else{281 $fp = @fopen($to.$header['filename'].'.gz','wb');282 if(!$fp) return(-1);283 $binary_data = pack('va1a1Va1a1', 0x8b1f, Chr($header['compression']),Chr(0x00), time(), Chr(0x00), Chr(3));284 fwrite($fp, $binary_data, 10);285 $size = $header['compressed_size'];286 while ($size != 0){287 $read_size = ($size < 1024 ? $size : 1024);288 $buffer = fread($zip, $read_size);289 $binary_data = pack('a'.$read_size, $buffer);290 @fwrite($fp, $binary_data, $read_size);291 $size -= $read_size;292 }293 $binary_data = pack('VV', $header['crc'], $header['size']);294 fwrite($fp, $binary_data,8); fclose($fp);295 $gzp = @gzopen($to.$header['filename'].'.gz','rb') or die("Cette archive est compress?");296 if(!$gzp) return(-2);297 $fp = @fopen($to.$header['filename'],'wb');298 if(!$fp) return(-1);299 $size = $header['size'];300 while ($size != 0){301 $read_size = ($size < 2048 ? $size : 2048);302 $buffer = gzread($gzp, $read_size);303 $binary_data = pack('a'.$read_size, $buffer);304 @fwrite($fp, $binary_data, $read_size);305 $size -= $read_size;306 }307 fclose($fp); gzclose($gzp);308 touch($to.$header['filename'], $header['mtime']);309 @unlink($to.$header['filename'].'.gz');310 }311 }312 return true;313 }314 public function addfiles($H_file='',$H_flist){315 //压缩文件 $H_flist = array(array('old.txt','new.txt'));316 $H_file = $H_file ==''?'temp_'.date('YmdHis').'.zip':$H_file;317 if(!is_array($H_flist)) return false;318 else{319 foreach($H_flist as $H_key => $H_val){320 //循环加入321 $H_oldfl = '';322 if(is_array($H_val)){323 $H_oldfl = $H_val[0];324 $H_newfl = $H_val[1];325 }else $H_oldfl = $H_newfl = $H_val;326 if($H_oldfl == '') continue;327 $H_filesize = @filesize($H_oldfl);328 $H_fp = @fopen($H_oldfl,'rb'); 329 $H_file_cont = Array($H_newfl,@fread($H_fp,$H_filesize));330 @fclose($H_fp);331 $this -> Add($H_file_cont,1); //添加文件332 }333 $this -> H_temnm = $H_file;334 if(@fputs(@fopen($H_file,"wb"),$this -> get_file())) return true;335 else return false;336 }337 return true;338 }339 }//End Class340 ?>