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

汉王 PHP 2016年01月12日 收藏

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

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

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

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

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

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