PHP打包下载整个文件夹或多文件


有时候需要输出服务器上某个文件夹的全部文件,比如备份网站,用下面的PHP函数来实现。

函数库代码PHPZip为:(请复制以下代码保存,以供调用)

  1. <?php
  2. Class PHPZip{
  3. Private $StrPath="../../@UpLoad";
  4. Private $datasec=array();
  5. Private $ctrl_dir=array();
  6. Private $eof_ctrl_dir="\x50\x4b\x05\x06\x00\x00\x00\x00";
  7. Private $old_offset=0;
  8. //压缩后下载
  9. Function DownLoad($curdir,$zipfilename,$out){
  10. $zipfilename=StrToLower($zipfilename);
  11. $curdir=Str_iReplace(basename($curdir),"",$curdir);
  12. chdir($curdir.$this->StrPath);
  13. header('Content-Encoding: none');
  14. header('Content-Type: application/zip');
  15. header('Content-Disposition: attachment ; filename='.Str_Replace(".zip","",basename($zipfilename)).'.zip');
  16. header('Pragma: no-cache');
  17. header('Expires: 0');
  18. print($out);
  19. }
  20. //压缩后保存在服务器,默认在/@Upload下
  21. Function SaveFile($curdir,$zipfilename,$out){
  22. $curdir=Str_iReplace(basename($curdir),"",$curdir);
  23. chdir($curdir.$this->StrPath);
  24. $fp=fopen($zipfilename,"wb");
  25. fwrite($fp,$out,strlen($out));
  26. fclose($fp);
  27. }
  28. //函数用途:压缩文件夹,递归逐层进行
  29. //参数详解:$dir需要压缩的目录,$zipfilename压缩后的文件名及存放路径,$Todo处理方式1提供下载2保存文件在服务器
  30. Function ZipDir($dir,$zipfilename,$Todo){
  31. IF(!@Function_exists('gzcompress')){Return 0;}
  32. @set_time_limit("0");
  33. $this->openFile($dir,$zipfilename);
  34. $out=$this -> filezip();
  35. Switch ($Todo){
  36. Case "1":
  37. $this -> DownLoad(__FILE__,$zipfilename,$out);
  38. Break;
  39. Case "2":
  40. $this -> SaveFile(__FILE__,$zipfilename,$out);
  41. Break;
  42. }
  43. }
  44. //函数用途:压缩文件,可以是单个也可以是数组的多个
  45. //参数详解:$file需要压缩的文件(可为数组),$zipfilename压缩后的文件名及存放路径,$Todo处理方式1提供下载2保存文件在服务器
  46. Function ZipFile($file,$zipfilename,$Todo){
  47. IF(!@Function_exists('gzcompress')){Return 0;}
  48. IF(is_array($file)){
  49. Foreach($file as $filename){
  50. IF(is_file($filename)){
  51. $fd= fopen ($filename, "rb");
  52. $content= @fread($fd, filesize ($filename));
  53. fclose ($fd);
  54. $filename= basename($filename);
  55. $this -> addFile($content, $filename);
  56. }
  57. }
  58. }Else{
  59. IF(is_file($file)){
  60. $fd= fopen ($file, "rb");
  61. $content= @fread($fd, filesize($file));
  62. fclose ($fd);
  63. $file= basename($file);
  64. $this -> addFile($content, $file);
  65. }
  66. }
  67. $out= $this -> filezip();
  68. Switch ($Todo){
  69. Case "1":
  70. $this -> DownLoad(__FILE__,$zipfilename,$out);
  71. Break;
  72. Case "2":
  73. $this -> SaveFile(__FILE__,$zipfilename,$out);
  74. Break;
  75. }
  76. }
  77. //递归取得下层文件夹下的文件
  78. Function openFile($path,$zipName){
  79. $temp_path=$path;
  80. $temp_zip_path=$zipName;
  81. IF($handle=@opendir($path)){
  82. While(false !== ($file=readdir($handle))){
  83. IF($file !='.' and $file !='..'){
  84. IF(ereg('\.' ,$file.@basename())){
  85. $fd=fopen($path.'/'.$file,"r");
  86. $fileValue=@fread($fd,1024000);
  87. fclose ($fd);
  88. $this -> addFile($fileValue,$path.'/'.$file);
  89. }Else{
  90. $this ->openFile($path.'/'.$file,$zipName.'/'.$file);
  91. }
  92. }
  93. }
  94. $zipName=$temp_zip_path;
  95. $path=$temp_path;
  96. closedir($handle);
  97. }
  98. }
  99. Function addFile($data,$name,$time=0){
  100. $name=str_replace('\\','/',$name);
  101. $name=str_replace('./','',str_replace('../','',$name));
  102. $dtime=dechex($this->unix2DosTime($time));
  103. $hexdtime='\x'.$dtime[6].$dtime[7].'\x'.$dtime[4].$dtime[5].'\x'.$dtime[2].$dtime[3].'\x'.$dtime[0].$dtime[1];
  104. Eval('$hexdtime="'.$hexdtime.'";');
  105. $fr="\x50\x4b\x03\x04";
  106. $fr.="\x14\x00";
  107. $fr.="\x00\x00";
  108. $fr.="\x08\x00";
  109. $fr.=$hexdtime;
  110. $unc_len=strlen($data);
  111. $crc=crc32($data);
  112. $zdata=gzcompress($data);
  113. $c_len=strlen($zdata);
  114. $zdata=substr(substr($zdata,0,strlen($zdata) - 4),2);
  115. $fr.=pack('V',$crc);
  116. $fr.=pack('V',$c_len);
  117. $fr.=pack('V',$unc_len);
  118. $fr.=pack('v',strlen($name));
  119. $fr.=pack('v',0);
  120. $fr.=$name;
  121. $fr.=$zdata;
  122. $fr.=pack('V',$crc);
  123. $fr.=pack('V',$c_len);
  124. $fr.=pack('V',$unc_len);
  125. $this -> datasec[]=$fr;
  126. $new_offset=strlen(implode('',$this->datasec));
  127. $cdrec="\x50\x4b\x01\x02";
  128. $cdrec.="\x00\x00";
  129. $cdrec.="\x14\x00";
  130. $cdrec.="\x00\x00";
  131. $cdrec.="\x08\x00";
  132. $cdrec.=$hexdtime;
  133. $cdrec.=pack('V',$crc);
  134. $cdrec.=pack('V',$c_len);
  135. $cdrec.=pack('V',$unc_len);
  136. $cdrec.=pack('v',strlen($name) );
  137. $cdrec.=pack('v',0 );
  138. $cdrec.=pack('v',0 );
  139. $cdrec.=pack('v',0 );
  140. $cdrec.=pack('v',0 );
  141. $cdrec.=pack('V',32 );
  142. $cdrec.=pack('V',$this -> old_offset );
  143. $this -> old_offset=$new_offset;
  144. $cdrec.=$name;
  145. $this -> ctrl_dir[]=$cdrec;
  146. }
  147. Function filezip(){
  148. $data=implode('',$this -> datasec);
  149. $ctrldir=implode('',$this -> ctrl_dir);
  150. Return
  151. $data.$ctrldir.$this -> eof_ctrl_dir .
  152. pack('v',sizeof($this -> ctrl_dir)) .
  153. pack('v',sizeof($this -> ctrl_dir)) .
  154. pack('V',strlen($ctrldir)) .
  155. pack('V',strlen($data))."\x00\x00";
  156. }
  157. Function unix2DosTime($unixtime=0){
  158. $timearray=($unixtime== 0) ? getdate() : getdate($unixtime);
  159. IF($timearray['year'] < 1980){
  160. $timearray['year']=1980;
  161. $timearray['mon']=1;
  162. $timearray['mday']=1;
  163. $timearray['hours']=0;
  164. $timearray['minutes']=0;
  165. $timearray['seconds']=0;
  166. }
  167. Return (($timearray['year'] - 1980) << 25) | ($timearray['mon'] << 21) | ($timearray['mday'] << 16) | ($timearray['hours'] << 11) | ($timearray['minutes'] << 5) | ($timearray['seconds'] >> 1);
  168. }
  169. /*
  170. 解压缩部分
  171. 用途:解压缩文件
  172. 参数:$zn需要解压缩的zip文件及路径,$to解压缩的目的地
  173. */
  174. Function Unzip_File($zn, $to, $index = Array(-1)){
  175. $ok = 0;
  176. $zip = @fopen($zn, 'rb');
  177. IF(!$zip){Return(-1);}
  178. $cdir = $this -> ReadCentralDir($zip, $zn);
  179. $pos_entry = $cdir['offset'];
  180. IF(!is_array($index)){
  181. $index = array($index);
  182. }
  183. For($i = 0; $index[$i];$i++){
  184. IF(intval($index[$i])!= $index[$i] || $index[$i] > $cdir['entries']){Return(-1);}
  185. }
  186. For($i=0;$i<$cdir['entries'];$i++){
  187. @fseek($zip, $pos_entry);
  188. $header = $this -> ReadCentralFileHeaders($zip);
  189. $header['index'] = $i;
  190. $pos_entry = ftell($zip);
  191. @rewind($zip);
  192. fseek($zip, $header['offset']);
  193. IF(in_array("-1", $index) || in_array($i, $index)){$stat[$header['filename']] = $this -> ExtractFile($header, $to, $zip);}
  194. }
  195. fclose($zip);
  196. Return $stat;
  197. }
  198. //取得压缩包内的文件信息
  199. Function get_List($zip_name){
  200. $zip = @fopen($zip_name, 'rb');
  201. IF(!$zip){Return(0);}
  202. $centd = $this -> ReadCentralDir($zip, $zip_name);
  203. @rewind($zip);
  204. @fseek($zip, $centd['offset']);
  205. For($i=0;$i<$centd['entries'];$i++){
  206. $header = $this -> ReadCentralFileHeaders($zip);
  207. $header['index'] = $i;
  208. $info['filename'] = $header['filename'];
  209. $info['stored_filename'] = $header['stored_filename'];
  210. $info['size'] = $header['size'];
  211. $info['compressed_size'] = $header['compressed_size'];
  212. $info['crc'] = strtoupper(dechex($header['crc']));
  213. $info['mtime'] = $header['mtime'];
  214. $info['comment'] = $header['comment'];
  215. $info['folder'] = ($header['external'] == 0x41FF0010 || $header['external'] == 16)?1:0;
  216. $info['index'] = $header['index'];
  217. $info['status'] = $header['status'];
  218. $ret[] = $info;
  219. unset($header);
  220. }
  221. Return $ret;
  222. }
  223. Function ReadFileHeader($zip){
  224. $binary_data = fread($zip, 30);
  225. $data = unpack('vchk/vid/vversion/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len', $binary_data);
  226. $header['filename'] = fread($zip, $data['filename_len']);
  227. IF($data['extra_len'] != 0){$header['extra'] = fread($zip, $data['extra_len']);}Else{$header['extra'] = '';}
  228. $header['compression'] = $data['compression'];
  229. $header['size'] = $data['size'];
  230. $header['compressed_size'] = $data['compressed_size'];
  231. $header['crc'] = $data['crc'];
  232. $header['flag'] = $data['flag'];
  233. $header['mdate'] = $data['mdate'];
  234. $header['mtime'] = $data['mtime'];
  235. IF($header['mdate'] && $header['mtime']){
  236. $hour = ($header['mtime']&0xF800) >> 11;
  237. $minute = ($header['mtime']&0x07E0) >> 5;
  238. $seconde = ($header['mtime']&0x001F) * 2;
  239. $year = (($header['mdate']&0xFE00) >> 9) + 1980;
  240. $month = ($header['mdate']&0x01E0) >> 5;
  241. $day = $header['mdate']&0x001F;
  242. $header['mtime'] = mktime($hour, $minute, $seconde, $month, $day, $year);
  243. }Else{
  244. $header['mtime'] = time();
  245. }
  246. $header['stored_filename'] = $header['filename'];
  247. $header['status'] = "ok";
  248. Return $header;
  249. }
  250. Function ReadCentralFileHeaders($zip){
  251. $binary_data = fread($zip, 46);
  252. $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);
  253. IF($header['filename_len'] != 0)
  254. $header['filename'] = fread($zip, $header['filename_len']);
  255. Else $header['filename'] = '';
  256. IF($header['extra_len'] != 0)
  257. $header['extra'] = fread($zip, $header['extra_len']);
  258. Else $header['extra'] = '';
  259. IF($header['comment_len'] != 0)
  260. $header['comment'] = fread($zip, $header['comment_len']);
  261. Else $header['comment'] = '';
  262. IF($header['mdate'] && $header['mtime']){
  263. $hour = ($header['mtime'] &0xF800) >> 11;
  264. $minute = ($header['mtime'] &0x07E0) >> 5;
  265. $seconde = ($header['mtime'] &0x001F) * 2;
  266. $year = (($header['mdate'] &0xFE00) >> 9) + 1980;
  267. $month = ($header['mdate'] &0x01E0) >> 5;
  268. $day = $header['mdate'] &0x001F;
  269. $header['mtime'] = mktime($hour, $minute, $seconde, $month, $day, $year);
  270. }Else{
  271. $header['mtime'] = time();
  272. }
  273. $header['stored_filename'] = $header['filename'];
  274. $header['status'] = 'ok';
  275. IF(substr($header['filename'], -1) == '/')
  276. $header['external'] = 0x41FF0010;
  277. Return $header;
  278. }
  279. Function ReadCentralDir($zip, $zip_name){
  280. $size = filesize($zip_name);
  281. IF($size < 277){$maximum_size = $size;}Else{$maximum_size = 277;}
  282. @fseek($zip, $size - $maximum_size);
  283. $pos = ftell($zip);
  284. $bytes = 0x00000000;
  285. While($pos < $size){
  286. $byte = @fread($zip, 1);
  287. $bytes = ($bytes << 8) | Ord($byte);
  288. IF($bytes == 0x504b0506){
  289. $pos++;
  290. break;
  291. }
  292. $pos++;
  293. }
  294. $data = unpack('vdisk/vdisk_start/vdisk_entries/ventries/Vsize/Voffset/vcomment_size', fread($zip, 18));
  295. IF($data['comment_size'] != 0){$centd['comment'] = fread($zip, $data['comment_size']);}Else{$centd['comment'] = '';}
  296. $centd['entries'] = $data['entries'];
  297. $centd['disk_entries'] = $data['disk_entries'];
  298. $centd['offset'] = $data['offset'];
  299. $centd['disk_start'] = $data['disk_start'];
  300. $centd['size'] = $data['size'];
  301. $centd['disk'] = $data['disk'];
  302. Return $centd;
  303. }
  304. Function ExtractFile($header, $to, $zip){
  305. $header = $this -> readfileheader($zip);
  306. IF(substr($to, -1) != "/") $to .= "/";
  307. IF(!@is_dir($to)) @mkdir($to, 0777);
  308. $pth = explode("/", dirname($header['filename']));
  309. For($i = 0;isset($pth[$i]);$i++){
  310. IF(!$pth[$i]) continue;
  311. $pthss .= $pth[$i] . "/";
  312. IF(!is_dir($to . $pthss)) @mkdir($to . $pthss, 0777);
  313. }
  314. IF(!($header['external'] == 0x41FF0010) && !($header['external'] == 16)){
  315. IF($header['compression'] == 0){
  316. $fp = @fopen($to . $header['filename'], 'wb');
  317. IF(!$fp) Return(-1);
  318. $size = $header['compressed_size'];
  319. While($size != 0){
  320. $read_size = ($size < 2048 ? $size : 2048);
  321. $buffer = fread($zip, $read_size);
  322. $binary_data = pack('a' . $read_size, $buffer);
  323. @fwrite($fp, $binary_data, $read_size);
  324. $size -= $read_size;
  325. }
  326. fclose($fp);
  327. touch($to . $header['filename'], $header['mtime']);
  328. }Else{
  329. $fp = @fopen($to . $header['filename'] . '.gz', 'wb');
  330. IF(!$fp) Return(-1);
  331. $binary_data = pack('va1a1Va1a1', 0x8b1f, Chr($header['compression']),
  332. Chr(0x00), time(), Chr(0x00), Chr(3));
  333. fwrite($fp, $binary_data, 10);
  334. $size = $header['compressed_size'];
  335. While($size != 0){
  336. $read_size = ($size < 1024 ? $size : 1024);
  337. $buffer = fread($zip, $read_size);
  338. $binary_data = pack('a' . $read_size, $buffer);
  339. @fwrite($fp, $binary_data, $read_size);
  340. $size -= $read_size;
  341. }
  342. $binary_data = pack('VV', $header['crc'], $header['size']);
  343. fwrite($fp, $binary_data, 8);
  344. fclose($fp);
  345. $gzp = @gzopen($to . $header['filename'] . '.gz', 'rb') or die("Cette archive est compress閑");
  346. IF(!$gzp) Return(-2);
  347. $fp = @fopen($to . $header['filename'], 'wb');
  348. IF(!$fp) Return(-1);
  349. $size = $header['size'];
  350. While($size != 0){
  351. $read_size = ($size < 2048 ? $size : 2048);
  352. $buffer = gzread($gzp, $read_size);
  353. $binary_data = pack('a' . $read_size, $buffer);
  354. @fwrite($fp, $binary_data, $read_size);
  355. $size -= $read_size;
  356. }
  357. fclose($fp);
  358. gzclose($gzp);
  359. touch($to . $header['filename'], $header['mtime']);
  360. @unlink($to . $header['filename'] . '.gz');
  361. }
  362. }
  363. Return true;
  364. }
  365. }
  366. ?>

使用方法:

函数:文件压缩
压缩参数:需要压缩的文件或文件夹(文件可为数组),压缩后的zip文件名及存放路径,压缩类型1:文件夹2:文件,后续操作1:压缩后下载;2:存放在服务器上(默认为/@Upload下)
压缩文件夹示例:Tozip("./","../".date("d-H-i-s").".zip",1,2);
压缩文件示例:
$aaa=array("../1.txt","../2.txt");
Tozip($aaa,"../2.zip",2);

用法举例:
比如有这样一段文件结构:
home
--upload
----1.jpg
----2.jpg
----3.jpg
--web
----html
------inc
--------zip.php(这是上面的代码库)
------download.php

使用download.php中的代码,实现upload文件夹打包并自动下载:

  1. <?php
  2. Function Tozip($Path,$ZipFile,$Typ=1,$Todo=1){
  3. //IF(!is_writeable($Path)){Exit("文件夹不可写!");}
  4. $Path=Str_iReplace("\\","/",($Path));
  5. IF(Is_Null($Path) Or Empty($Path) Or !IsSet($Path)){Return False;}
  6. IF(Is_Null($ZipFile) Or Empty($ZipFile) Or !IsSet($ZipFile)){Return False;}
  7. Include_once("inc/zip.php"); // 载入代码库,注意路径
  8. $zip = New PHPZip;
  9. IF(SubStr($Path,-1,1)=="/"){$Path=SubStr($Path,0,StrLen($Path)-1);}
  10. OB_end_clean();
  11. Switch ($Typ){
  12. Case "1":
  13. $zip->ZipDir($Path,$ZipFile,$Todo);
  14. Break;
  15. Case "2":
  16. $zip->ZipFile($Path,$ZipFile,$Todo);
  17. Break;
  18. }
  19. IF($Todo==1){
  20. Die();
  21. }Else{
  22. Return True;
  23. }
  24. }
  25. Tozip("././upload", "../../upload.zip",1,1)
  26. ?>

//最然转载这个,但是个人认为这种相对路径,最好不要在上传下载的时候用,容易引发漏洞。能用绝对路径就用绝对路径...





posted @ 2014-11-24 11:29  SunsCheung  阅读(873)  评论(0编辑  收藏  举报