学什么之PHPZIP压缩与解压
<?PHP 类PHPZip { private $ ctrl_dir = array(); private $ datasec = array(); / ******************* ********* *压缩部分 ************************************************** ******** / // ------------------------------------------------ ------ // //#遍历指定文件夹 // // $ archive = new PHPZip(); // $ filelist = $ archive-> visitFile(文件夹路径); //打印“当前文件夹的文件:<p> \ r \ n”; // foreach($ filelist as $ file) // printf(“%s <br> \ r \ n”,$ file); // ------------------------------------------------ ------ // var $ fileList = array(); 公共职能visitFile($路径) { 全局$ fileList; $ path = str_replace(“\\”,“/”,$ path); $ fdir = dir($ path); while(($ file = $ fdir-> read())!== false) { if($ file =='。'|| $ file =='..'){continue; } $ pathSub = preg_replace(“* / {2,} *”,“/”,$ path。“/”。$ file); //替换多个反斜杠 $ fileList [] = is_dir($ pathSub)?$ pathSub。“/”:$ pathSub; if(is_dir($ pathSub)){$ this-> visitFile($ pathSub); } } $ fdir->接近(); 返回$ fileList; } 私有函数unix2DosTime($ unixtime = 0) { $ timearray =($ unixtime == 0)?getdate():getdate($ unixtime); 如果($ timearray ['year'] <1980) { $ timearray ['year'] = 1980; $ timearray ['mon'] = 1; $ timearray ['mday'] = 1; $ timearray ['hours'] = 0; $ timearray ['minutes'] = 0; $ timearray ['seconds'] = 0; } (($ timearray ['year'] - 1980)<< 25) | ($ timearray ['mon'] << 21) | ($ timearray ['mday'] << 16) | ($ timearray ['hours'] << 11) | ($ timearray ['minutes'] << 5) | ($ timearray ['seconds'] >> 1); } var $ old_offset = 0; 私人函数addFile($ data,$ filename,$ time = 0) { $ filename = str_replace('\\','/',$ filename); $ 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”; $ fr。=“\ x00 \ x00”; $ fr。=“\ x08 \ x00”; $ fr。= $ hexdtime; $ unc_len = strlen($ data); $ crc = crc32($ data); $ zdata = gzcompress($ data); $ c_len = strlen($ zdata); $ zdata = substr(substr($ zdata,0,strlen($ zdata) - 4),2); $ fr。= pack('V',$ crc); $ fr。= pack('V',$ c_len); $ fr。= pack('V',$ unc_len); $ fr。= pack('v',strlen($ filename)); $ fr。= pack('v',0); $ fr。= $ filename; $ fr。= $ zdata; $ fr。= pack('V',$ crc); $ fr。= pack('V',$ c_len); $ fr。= pack('V',$ unc_len); $ this-> datasec [] = $ fr; $ new_offset = strlen(implode('',$ this-> datasec)); $ 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($ filename)); $ 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 = $ new_offset; $ cdrec。= $ filename; $ this-> ctrl_dir [] = $ cdrec; } var $ eof_ctrl_dir =“\ x50 \ x4b \ x05 \ x06 \ x00 \ x00 \ x00 \ x00”; 私人功能文件() { $ data = implode('',$ this-> datasec); $ ctrldir = implode('',$ this-> ctrl_dir); 返回$数据 。$ ctrldir 。$这个 - > 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”; } // ------------------------------------------------ ------ // //#压缩到服务器 // // $ archive = new PHPZip(); // $ archive-> Zip(“需压缩的文件所在目录”,“ZIP压缩文件名”); // ------------------------------------------------ ------ // 公共函数Zip($ dir,$ saveName) { 如果(@!function_exists('gzcompress')){return; } // ob_end_clean(); $ filelist = $ this-> visitFile($ dir); if(count($ filelist)== 0){return; } foreach($ filelist为$ file) { 如果(!file_exists($ file)||!is_file($ file)){continue; } $ fd = fopen($ file,“rb”); $ content = @fread($ fd,filesize($ file)); FCLOSE($ FD); // 1.删除$ dir的字符(./folder/file.txt删除./文件夹/) // 2.如果存在/就删除(/file.txt删除/) $ file = substr($ file,strlen($ dir)); if(substr($ file,0,1)==“\\”|| substr($ file,0,1)==“/”){$ file = substr($ file,1); } $ this-> addFile($ content,$ file); } $ out = $ this-> file(); $ fp = fopen($ saveName,“wb”); fwrite($ fp,$ out,strlen($ out)); FCLOSE($ FP); } // ------------------------------------------------ ------ // //#压缩并直接下载 // // $ archive = new PHPZip(); // $ archive-> ZipAndDownload(“需压缩的文件所在目录”); // ------------------------------------------------ ------ // 公共函数ZipAndDownload($ dir,$ saveName) { 如果(@!function_exists('gzcompress')){return; } ob_end_clean(); $ filelist = $ this-> visitFile($ dir); if(count($ filelist)== 0){return; } foreach($ filelist为$ file) { 如果(!file_exists($ file)||!is_file($ file)){continue; } $ fd = fopen($ file,“rb”); $ content = @fread($ fd,filesize($ file)); FCLOSE($ FD); // 1.删除$ dir的字符(./folder/file.txt删除./文件夹/) // 2.如果存在/就删除(/file.txt删除/) $ file = substr($ file,strlen($ dir)); if(substr($ file,0,1)==“\\”|| substr($ file,0,1)==“/”){$ file = substr($ file,1); } $ this-> addFile($ content,$ file); } $ out = $ this-> file(); @header('Content-Encoding:none'); @header('Content-Type:application / zip'); @header('Content-Disposition:attachment; filename ='。$ saveName。'。zip'); @header('Pragma:no-cache'); @header('Expires:0'); 打印($出); } / ******************* ********* *解压部分 ************************************************** ******** / // ------------------------------------------------ ------ // // ReadCentralDir($ zip,$ zipfile) // $ zip是经过@fopen($ zipfile,'rb')打开的 // $ zipfile是zip文件的路径 // ------------------------------------------------ ------ // 私人函数ReadCentralDir($ zip,$ zipfile) { $ size = filesize($ zipfile); $ max_size =($ size <277)?$ size:277; @fseek($ zip,$ size - $ max_size); $ pos = ftell($ zip); $ bytes = 0x00000000; while($ pos <$ size) { $ byte = @fread($ zip,1); $ bytes =($ bytes << 8)| 奥德($字节); $ POS ++; if($ bytes == 0x504b0506){break; } } $ data = unpack('vdisk / vdisk_start / vdisk_entries / ventries / Vsize / Voffset / vcomment_size',fread($ zip,18)); $ centd ['comment'] =($ data ['comment_size']!= 0)?fread($ zip,$ data ['comment_size']):''; //注释 $ centd ['entries'] = $ data ['entries']; $ centd ['disk_entries'] = $ data ['disk_entries']; $ centd ['offset'] = $ data ['offset']; $ centd ['disk_start'] = $ data ['disk_start']; $ centd ['size'] = $ data ['size']; $ centd ['disk'] = $ data ['disk']; 返回$ centd; } 私人函数ReadCentralFileHeaders($ zip) { $ binary_data = fread($ zip,46); $ 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); $ header ['filename'] =($ header ['filename_len']!= 0)?fread($ zip,$ header ['filename_len']):''; $ header ['extra'] =($ header ['extra_len']!= 0)?fread($ zip,$ header ['extra_len']):''; $ header ['comment'] =($ header ['comment_len']!= 0)?fread($ zip,$ header ['comment_len']):''; if($ header ['mdate'] && $ header ['mtime']) { $ hour =($ header ['mtime']&0xF800)>> 11; $ minute =($ header ['mtime']&0x07E0)>> 5; $ seconde =($ header ['mtime']&0x001F)* 2; $ year =(($ header ['mdate']&0xFE00)>> 9)+ 1980; $ month =($ header ['mdate']&0x01E0)>> 5; $ day = $ header ['mdate']&0x001F; $ header ['mtime'] = mktime($ hour,$ minute,$ seconde,$ month,$ day,$ year); } else { $ header ['mtime'] = time(); } $ header ['stored_filename'] = $ header ['filename']; $ header ['status'] ='ok'; if(substr($ header ['filename'],-1)=='/'){$ header ['external'] = 0x41FF0010; } //判断是否文件夹 返回$ header; } 私人函数ReadFileHeader($ zip) { $ binary_data = fread($ zip,30); $ data = unpack('vchk / vid / vversion / vflag / vcompression / vmtime / vmdate / Vcrc / Vcompressed_size / Vsize / vfilename_len / vextra_len',$ binary_data); $ header ['filename'] = fread($ zip,$ data ['filename_len']); $ header ['extra'] =($ data ['extra_len']!= 0)?fread($ zip,$ data ['extra_len']):''; $ header ['compression'] = $ data ['compression']; $ header ['size'] = $ data ['size']; $ header ['compressed_size'] = $ data ['compressed_size']; $ header ['crc'] = $ data ['crc']; $ header ['flag'] = $ data ['flag']; $ header ['mdate'] = $ data ['mdate']; $ header ['mtime'] = $ data ['mtime']; if($ header ['mdate'] && $ header ['mtime']){ $ hour =($ header ['mtime']&0xF800)>> 11; $ minute =($ header ['mtime']&0x07E0)>> 5; $ seconde =($ header ['mtime']&0x001F)* 2; $ year =(($ header ['mdate']&0xFE00)>> 9)+ 1980; $ month =($ header ['mdate']&0x01E0)>> 5; $ day = $ header ['mdate']&0x001F; $ header ['mtime'] = mktime($ hour,$ minute,$ seconde,$ month,$ day,$ year); }其他{ $ header ['mtime'] = time(); } $ header ['stored_filename'] = $ header ['filename']; $ header ['status'] =“ok”; 返回$ header; } 私人函数ExtractFile($ header,$ to,$ zip) { $ header = $ this-> readfileheader($ zip); if(substr($ to,-1)!=“/”){$ to。=“/”; } 如果(!@ is_dir($ to)){@mkdir($ to,0777); } $ pth = explode(“/”,dirname($ header ['filename'])); for($ i = 0; isset($ pth [$ i]); $ i ++){ 如果(!$ pth [$ i]){continue; } $ pthss。= $ pth [$ i]。“/”; if(!is_dir($ to。$ pthss)){@mkdir($ to。$ pthss,0777); } } if(!($ header ['external'] == 0x41FF0010)&&!($ header ['external'] == 16)) { 如果($ header ['compression'] == 0) { $ fp = @fopen($ to。$ header ['filename'],'wb'); if(!$ fp){return(-1); } $ size = $ header ['compressed_size']; 而($ size!= 0) { $ read_size =($ size <2048?$ size:2048); $ buffer = fread($ zip,$ read_size); $ binary_data = pack('a'。$ read_size,$ buffer); @fwrite($ fp,$ binary_data,$ read_size); $ size - = $ read_size; } FCLOSE($ FP); touch($ to。$ header ['filename'],$ header ['mtime']); }其他{ $ fp = @fopen($ to。$ header ['filename']。'。gz','wb'); if(!$ fp){return(-1); } $ binary_data = pack('va1a1Va1a1',0x8b1f,Chr($ header ['compression']),Chr(0x00),time(),Chr(0x00),Chr(3)); fwrite($ fp,$ binary_data,10); $ size = $ header ['compressed_size']; 而($ size!= 0) { $ read_size =($ size <1024?$ size:1024); $ buffer = fread($ zip,$ read_size); $ binary_data = pack('a'。$ read_size,$ buffer); @fwrite($ fp,$ binary_data,$ read_size); $ size - = $ read_size; } $ binary_data = pack('VV',$ header ['crc'],$ header ['size']); fwrite($ fp,$ binary_data,8); FCLOSE($ FP); $ gzp = @gzopen($ to。$ header ['filename']。'。gz','rb')或die(“Cette archive est compress!”); if(!$ gzp){return(-2); } $ fp = @fopen($ to。$ header ['filename'],'wb'); if(!$ fp){return(-1); } $ size = $ header ['size']; 而($ size!= 0) { $ read_size =($ size <2048?$ size:2048); $ buffer = gzread($ gzp,$ read_size); $ binary_data = pack('a'。$ read_size,$ buffer); @fwrite($ fp,$ binary_data,$ read_size); $ size - = $ read_size; } FCLOSE($ FP); gzclose($滚子坪); touch($ to。$ header ['filename'],$ header ['mtime']); @unlink($到$头[ '文件名']。 'GZ。'); } } 返回true; } // ------------------------------------------------ ------ // //#解压文件 // // $ archive = new PHPZip(); // $ zipfile =“ZIP压缩文件名”; // $ savepath =“解压缩目录名”; // $ zipfile = $ unzipfile; // $ savepath = $ unziptarget; // $ array = $ archive-> GetZipInnerFilesInfo($ zipfile); // $ filecount = 0; // $ dircount = 0; // $ failfiles = array(); // set_time_limit(0); //修改为不限制超时时间(默认为30秒) // // for($ i = 0; $ i <count($ array); $ i ++){ // if($ array [$ i] [folder] == 0){ // if($ archive-> unZip($ zipfile,$ savepath,$ i)> 0){ // $ filecount ++; //} else { // $ failfiles [] = $ array [$ i] [filename]; //} //} else { // $ dircount ++; //} //} // set_time_limit(30); // printf(“文件夹:%d&nbsp;&nbsp;&nbsp;&nbsp;解压文件:%d&nbsp;&nbsp;&nbsp;&nbsp;失败:%d <br> \ r \ n”,$ dircount,$ filecount,count( $ failfiles)); // if(count($ failfiles)> 0){ // foreach($ failfiles as $ file){ // printf(“&middot;%s <br> \ r \ n”,$ file); //} //} // ------------------------------------------------ ------ // 公共函数unZip($ zipfile,$ to,$ index = Array(-1)) { $ ok = 0; $ zip = @fopen($ zipfile,'rb'); 如果(!$ zip){return(-1); } $ cdir = $ this-> ReadCentralDir($ zip,$ zipfile); $ pos_entry = $ cdir ['offset']; if(!is_array($ index)){$ index = array($ index); } for($ i = 0; $ index [$ i]; $ i ++) { if(intval($ index [$ i])!= $ index [$ i] || $ index [$ i]> $ cdir ['entries']) { 返回(-1); } } for($ i = 0; $ i <$ cdir ['entries']; $ i ++) { @fseek($ zip,$ pos_entry); $ header = $ this-> ReadCentralFileHeaders($ zip); $ header ['index'] = $ i; $ pos_entry = ftell($ zip); @rewind($ ZIP); fseek($ zip,$ header ['offset']); if(in_array(“ - 1”,$ index)|| in_array($ i,$ index)) { $ stat [$ header ['filename']] = $ this-> ExtractFile($ header,$ to,$ zip); } } FCLOSE($ ZIP); 返回$ stat; } / ******************* ********* *其它部分 ************************************************** ******** / // ------------------------------------------------ ------ // //#获取被压缩文件的信息 // // $ archive = new PHPZip(); // $ array = $ archive-> GetZipInnerFilesInfo(ZIP压缩文件名); // for($ i = 0; $ i <count($ array); $ i ++){ // printf(“<b>&middot;%s </ b> <br> \ r \ n”,$ array [$ i] [filename]); // foreach($ array [$ i] as $ key => $ value) // printf(“%s =>%s <br> \ r \ n”,$ key,$ value); // print“\ r \ n <p> ------------------------------------ <p> \ r \ n \ r \ n“个; //} // ------------------------------------------------ ------ // 公共函数GetZipInnerFilesInfo($ zipfile) { $ zip = @fopen($ zipfile,'rb'); 如果(!$ zip){return(0); } $ centd = $ this-> ReadCentralDir($ zip,$ zipfile); @rewind($ ZIP); @fseek($ zip,$ centd ['offset']); $ ret = array(); for($ i = 0; $ i <$ centd ['entries']; $ i ++) { $ header = $ this-> ReadCentralFileHeaders($ zip); $ header ['index'] = $ i; $ info = array( 'filename'=> $ header ['filename'],//文件名 'stored_filename'=> $ header ['stored_filename'],//压缩后文件名 'size'=> $ header ['size'],//大小 'compressed_size'=> $ header ['compressed_size'],//压缩后大小 'crc'=> strtoupper(dechex($ header ['crc'])),// CRC32 'mtime'=> date(“Ymd H:i:s”,$ header ['mtime']),//文件修改时间 'comment'=> $ header ['comment'],//注释 'folder'=>($ header ['external'] == 0x41FF0010 || $ header ['external'] == 16)?1:0,//是否为文件夹 'index'=> $ header ['index'],//文件索引 'status'=> $ header ['status'] //状态 ); $ ret [] = $ info; 未设置($头); } FCLOSE($ ZIP); 返回$ ret; } // ------------------------------------------------ ------ // //#获取压缩文件的注释 // // $ archive = new PHPZip(); // echo $ archive-> GetZipComment(ZIP压缩文件名); // ------------------------------------------------ ------ // 公共函数GetZipComment($ zipfile) { $ zip = @fopen($ zipfile,'rb'); 如果(!$ zip){return(0); } $ centd = $ this-> ReadCentralDir($ zip,$ zipfile); FCLOSE($ ZIP); 返回$ centd [comment]; } }