[PHP] php压缩zip文件 zip压缩文件创建类 →→→→→进入此内容的聊天室

来自 , 2020-06-12, 写在 PHP, 查看 97 次.
URL http://www.code666.cn/view/1264a061
  1. <?php
  2. /*
  3.  * Zip file creation class.
  4.  * Makes zip files.
  5.  *
  6.  * Based on :
  7.  *
  8.  *  http://www.zend.com/codex.php?id=535&single=1
  9.  *  By Eric Mueller <eric@themepark.com>
  10.  *
  11.  *  http://www.zend.com/codex.php?id=470&single=1
  12.  *  by Denis125 <webmaster@atlant.ru>
  13.  *
  14.  *  a patch from Peter Listiak <mlady@users.sourceforge.net> for last modified
  15.  *  date and time of the compressed file
  16.  *
  17.  * Official ZIP file format: http://www.pkware.com/company/standards/appnote/appnote.txt
  18.  *
  19.  */
  20.  
  21. class zipfile{
  22.         # Array to store compressed data
  23.         var $datasec = Array();
  24.        
  25.         # Central directory
  26.         var $ctrl_dir = Array();
  27.        
  28.         # End of central directory record
  29.         var $eof_ctrl_dir = "\x50\x4b\x05\x06\x00\x00\x00\x00";
  30.        
  31.         # Last offset position
  32.         var $old_offset = 0;
  33.        
  34.         var $print = false;
  35.        
  36.         var $zlib = false;
  37.        
  38.         function zipfile(){
  39.                 $this->zlib = extension_loaded("zlib") and function_exists("gzopen");
  40.         }
  41.  
  42.         # Converts an Unix timestamp to a four byte DOS date and time format (date
  43.         # in high two bytes, time in low two bytes allowing magnitude comparison).
  44.         function unix2DosTime($unixtime = 0){
  45.                 $timearray = ($unixtime == 0) ? getdate() : getdate($unixtime);
  46.                
  47.                 if($timearray['year'] < 1980){
  48.                         $timearray['year'] = 1980;
  49.                         $timearray['mon'] = 1;
  50.                         $timearray['mday'] = 1;
  51.                         $timearray['hours'] = 0;
  52.                         $timearray['minutes'] = 0;
  53.                         $timearray['seconds'] = 0;
  54.                 }
  55.                
  56.                 return (($timearray['year'] - 1980) << 25) | ($timearray['mon'] << 21) | ($timearray['mday'] << 16) | ($timearray['hours'] << 11) | ($timearray['minutes'] << 5) | ($timearray['seconds'] >> 1);
  57.         }
  58.        
  59.         function addTree($dir, $removePath){
  60.                 $files = Array();
  61.                
  62.                 $d = dir($dir);
  63.                
  64.                 while($file = $d->read())
  65.                         if($file != "." and $file != "..")
  66.                                 array_push($files, $file);
  67.                
  68.                 if(sizeof($files) == 0){
  69.                         $this->addDirectory(str_replace($removePath, "", $dir));
  70.                 }else{
  71.                         foreach($files as $file){
  72.                                 if(is_dir($dir . "/" . $file)){
  73.                                         $this->addTree($dir . "/" . $file, $removePath);
  74.                                 }else{
  75.                                         $this->addFile($dir . "/" . $file, str_replace($removePath, "", $dir . "/" . $file), filemtime($dir . "/" . $file));
  76.                                 }
  77.                         }
  78.                 }
  79.         }
  80.        
  81.         function getFileData($filename){
  82.                 $handle = fopen($filename, "rb");
  83.                
  84.                 if(!$handle)
  85.                         die("File '$filename' can not be opened !");
  86.  
  87.                 $data = filesize($filename) > 0 ? fread($handle, filesize($filename)) : "";
  88.                 fclose($handle);
  89.  
  90.                 return $data;
  91.         }
  92.        
  93.         function addDirectory($name){
  94.  
  95.                 $name = str_replace("\\", "/", $name);
  96.  
  97.                 if(!substr($name, -1) != "/")
  98.                         $name .= "/";
  99.  
  100.                 $fr = "\x50\x4b\x03\x04\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00";
  101.                
  102.                 $fr .= pack("V",0);
  103.                 $fr .= pack("V",0);
  104.                 $fr .= pack("V",0);
  105.                 $fr .= pack("v", strlen($name));
  106.                 $fr .= pack("v", 0);
  107.                 $fr .= $name . pack("V", 0);
  108.                 $fr .= pack("V", 0);
  109.                 $fr .= pack("V", 0);
  110.                
  111.                 $this -> datasec[] = $fr;
  112.                
  113.                 $new_offset = strlen(implode("", $this->datasec));
  114.                
  115.                 $cdrec = "\x50\x4b\x01\x02\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00";
  116.                 $cdrec .= pack("V",0);
  117.                 $cdrec .= pack("V",0);
  118.                 $cdrec .= pack("V",0);
  119.                 $cdrec .= pack("v", strlen($name));
  120.                
  121.                 $cdrec .= pack("v", 0);
  122.                 $cdrec .= pack("v", 0);
  123.                 $cdrec .= pack("v", 0);
  124.                 $cdrec .= pack("v", 0);
  125.                
  126.                 $ext = "\xff\xff\xff\xff";
  127.                 $cdrec .= pack("V", 16);
  128.                 $cdrec .= pack("V", $this->old_offset);
  129.                 $cdrec .= $name;
  130.  
  131.                 $this -> ctrl_dir[] = $cdrec;
  132.                 $this -> old_offset = $new_offset;
  133.                 $this -> dirs[] = $name;
  134.         }
  135.        
  136.         # Adds "file" to archive
  137.         function addFile($filename, $name, $time = 0){
  138.  
  139.                 $name = str_replace('\\', '/', $name);
  140.                
  141.                 $data = $this->getFileData($filename);
  142.                 $dtime = dechex($this->unix2DosTime($time));
  143.                
  144.                 $hexdtime = '\x' . $dtime[6] . $dtime[7] . '\x' . $dtime[4] . $dtime[5] . '\x' . $dtime[2] . $dtime[3] . '\x' . $dtime[0] . $dtime[1];
  145.                 eval('$hexdtime = "' . $hexdtime . '";');
  146.                
  147.                 $fr  = "\x50\x4b\x03\x04";
  148.                 $fr .= "\x14\x00";      // ver needed to extract
  149.                 $fr .= "\x00\x00";      // gen purpose bit flag
  150.                 $fr .= "\x08\x00";      // compression method
  151.                 $fr .= $hexdtime;               // last mod time and date
  152.  
  153.                 // "local file header" segment
  154.                 $unc_len = strlen($data);
  155.                 $crc     = crc32($data);
  156.                
  157.                 $zdata   = gzcompress($data);
  158.                
  159.                 $zdata   = substr(substr($zdata, 0, strlen($zdata) - 4), 2); // fix crc bug
  160.                 $c_len   = strlen($zdata);
  161.                 $fr      .= pack('V', $crc);             // crc32
  162.                 $fr      .= pack('V', $c_len);           // compressed filesize
  163.                 $fr      .= pack('V', $unc_len);         // uncompressed filesize
  164.                 $fr      .= pack('v', strlen($name));    // length of filename
  165.                 $fr      .= pack('v', 0);                // extra field length
  166.                 $fr      .= $name;
  167.  
  168.                 // "file data" segment
  169.                 $fr .= $zdata;
  170.  
  171.                 // "data descriptor" segment (optional but necessary if archive is not served as file)
  172.                 $fr .= pack('V', $crc);                 // crc32
  173.                 $fr .= pack('V', $c_len);               // compressed filesize
  174.                 $fr .= pack('V', $unc_len);             // uncompressed filesize
  175.  
  176.                 // add this entry to array
  177.                 $this -> datasec[] = $fr;
  178.  
  179.                 // now add to central directory record
  180.                 $cdrec = "\x50\x4b\x01\x02";
  181.                 $cdrec .= "\x00\x00";                // version made by
  182.                 $cdrec .= "\x14\x00";                // version needed to extract
  183.                 $cdrec .= "\x00\x00";                // gen purpose bit flag
  184.                 $cdrec .= "\x08\x00";                // compression method
  185.                 $cdrec .= $hexdtime;                 // last mod time & date
  186.                 $cdrec .= pack('V', $crc);           // crc32
  187.                 $cdrec .= pack('V', $c_len);         // compressed filesize
  188.                 $cdrec .= pack('V', $unc_len);       // uncompressed filesize
  189.                 $cdrec .= pack('v', strlen($name) ); // length of filename
  190.                 $cdrec .= pack('v', 0 );             // extra field length
  191.                 $cdrec .= pack('v', 0 );             // file comment length
  192.                 $cdrec .= pack('v', 0 );             // disk number start
  193.                 $cdrec .= pack('v', 0 );             // internal file attributes
  194.                 $cdrec .= pack('V', 32 );            // external file attributes - 'archive' bit set
  195.  
  196.                 $cdrec .= pack('V', $this -> old_offset ); // relative offset of local header
  197.                 $this -> old_offset += strlen($fr);
  198.  
  199.                 $cdrec .= $name;
  200.  
  201.                 // optional extra field, file comment goes here
  202.                 // save to central directory
  203.                 $this -> ctrl_dir[] = $cdrec;
  204.         }
  205.        
  206.         # Dumps out file
  207.         function file(){
  208.                 $data = implode('', $this->datasec);
  209.                 $ctrldir = implode('', $this->ctrl_dir);
  210.                
  211.                 return $data . $ctrldir . $this -> eof_ctrl_dir .
  212.                                                 pack('v', sizeof($this -> ctrl_dir)) .  // total # of entries "on this disk"
  213.                                                 pack('v', sizeof($this -> ctrl_dir)) .  // total # of entries overall
  214.                                                 pack('V', strlen($ctrldir)) .           // size of central dir
  215.                                                 pack('V', strlen($data)) .              // offset to start of central dir
  216.                                                 "\x00\x00";                             // .zip file comment length
  217.         }
  218.        
  219.         function writeFile($filename){
  220.                 $handle = fopen($filename, "w");
  221.                 fwrite($handle, $this->file());
  222.                 fclose($handle);
  223.         }
  224.  
  225.  
  226.         function getContentList($filename){
  227.                 $handle = fopen($filename, 'rb');
  228.                
  229.                 if(!$handle)
  230.                         die("File '$filename' not found!");
  231.                
  232.                 $cd = $this->readCentralDir($handle, $filename);
  233.                
  234.                 rewind($handle);
  235.                 fseek($handle, $cd['offset']);
  236.                
  237.                 $list = Array();
  238.                
  239.                 for($i = 0; $i < $cd['entries']; $i ++){
  240.                
  241.                         $header = $this->readCentralFileHeader($handle);
  242.                         $header['index'] = $i;
  243.                        
  244.                         $info['filename'] = $header['filename'];
  245.                         $info['stored_filename'] = $header['stored_filename'];
  246.                         $info['size'] = $header['size'];
  247.                         $info['compressed_size'] = $header['compressed_size'];
  248.                         $info['crc'] = strtoupper(dechex($header['crc']));
  249.                         $info['mtime'] = $header['mtime'];
  250.                         $info['comment'] = $header['comment'];
  251.                         $info['folder'] = ($header['external'] == 0x41FF0010 || $header['external'] == 16) ? 1 : 0;
  252.                         $info['index'] = $header['index'];
  253.                         $info['status'] = $header['status'];
  254.                        
  255.                         array_push($list, $info);
  256.                        
  257.                         unset($header);
  258.    }
  259.          return $list;
  260.  }
  261.  
  262.         function readFileHeader($handle){
  263.                 $binary_data = fread($handle, 30);
  264.                
  265.                 $data = unpack('vchk/vid/vversion/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len', $binary_data);
  266.                
  267.                 $header['filename'] = fread($handle, $data['filename_len']);
  268.                 $header['extra'] = $data['extra_len'] != 0 ? fread($handle, $data['extra_len']) : "";
  269.                 $header['compression'] = $data['compression'];
  270.                 $header['size'] = $data['size'];
  271.                 $header['compressed_size'] = $data['compressed_size'];
  272.                 $header['crc'] = $data['crc'];
  273.                 $header['flag'] = $data['flag'];
  274.                 $header['mdate'] = $data['mdate'];
  275.                 $header['mtime'] = $data['mtime'];
  276.                
  277.                 if($header['mdate'] && $header['mtime']){
  278.                         $hour = ($header['mtime']&0xF800) >> 11;
  279.                         $minute = ($header['mtime']&0x07E0) >> 5;
  280.                         $seconde = ($header['mtime']&0x001F) * 2;
  281.                         $year = (($header['mdate']&0xFE00) >> 9) + 1980;
  282.                         $month = ($header['mdate']&0x01E0) >> 5;
  283.                         $day = $header['mdate']&0x001F;
  284.                         $header['mtime'] = mktime($hour, $minute, $seconde, $month, $day, $year);
  285.                 }else{
  286.                         $header['mtime'] = time();
  287.                 }
  288.                
  289.                 $header['stored_filename'] = $header['filename'];
  290.                 $header['status'] = "ok";
  291.                 return $header;
  292.         }
  293.        
  294.         function readCentralFileHeader($handle){
  295.                 $binary_data = fread($handle, 46);
  296.                
  297.                 $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);
  298.                
  299.                 $header['filename'] = $header['filename_len'] != 0 ? fread($handle,$header['filename_len']) : "";
  300.                 $header['extra'] = $header['extra_len'] != 0 ? fread($handle, $header['extra_len']) : "";
  301.                 $header['comment'] = $header['comment_len'] != 0 ? fread($handle, $header['comment_len']) : "";
  302.  
  303.                 if($header['mdate'] && $header['mtime']){
  304.                         $hour = ($header['mtime']&0xF800) >> 11;
  305.                         $minute = ($header['mtime']&0x07E0) >> 5;
  306.                         $seconde = ($header['mtime']&0x001F) * 2;
  307.                         $year = (($header['mdate']&0xFE00) >> 9) + 1980;
  308.                         $month = ($header['mdate']&0x01E0) >> 5;
  309.                         $day = $header['mdate']&0x001F;
  310.                        
  311.                         $header['mtime'] = mktime($hour, $minute, $seconde, $month, $day, $year);
  312.                 }else{
  313.                         $header['mtime'] = time();
  314.                 }
  315.                
  316.                 $header['stored_filename'] = $header['filename'];
  317.                 $header['status'] = 'ok';
  318.                
  319.                 if(substr($header['filename'], -1) == '/')
  320.                         $header['external'] = 0x41FF0010;
  321.                
  322.                 return $header;
  323.         }
  324.  
  325.         function readCentralDir($handle, $filename){
  326.                 $size = filesize($filename);
  327.                
  328.                 $maximum_size = $size < 277 ? $size : 277;
  329.                
  330.                 fseek($handle, $size - $maximum_size);
  331.                 $pos = ftell($handle);
  332.                 $bytes = 0x00000000;
  333.                
  334.                 while($pos < $size){
  335.                         $byte = fread($handle, 1);
  336.                         $bytes = ($bytes << 8) | Ord($byte);
  337.                        
  338.                         if($bytes == 0x504b0506){
  339.                                 $pos++;
  340.                                 break;
  341.                         }
  342.                         $pos++;
  343.                 }
  344.                
  345.                 $data = unpack('vdisk/vdisk_start/vdisk_entries/ventries/Vsize/Voffset/vcomment_size', fread($handle, 18));
  346.                
  347.                 if($data['comment_size'] != 0)
  348.                         $cd['comment'] = fread($handle, $data['comment_size']);
  349.     else
  350.                         $cd['comment'] = '';
  351.                
  352.                 $cd['entries'] = $data['entries'];
  353.                 $cd['disk_entries'] = $data['disk_entries'];
  354.                 $cd['offset'] = $data['offset'];
  355.                 $cd['disk_start'] = $data['disk_start'];
  356.                 $cd['size'] = $data['size'];
  357.                 $cd['disk'] = $data['disk'];
  358.                
  359.                 return $cd;
  360.         }
  361.        
  362.         function extract($filename, $targetDir, $index = Array()){
  363.  
  364.                 if(!is_dir($targetDir))
  365.                         mkdir($targetDir, 0755);
  366.                        
  367.                 if(substr($targetDir, -1) != "/")
  368.                         $targetDir .= "/";
  369.                        
  370.                 $inHandle = fopen($filename, 'rb');
  371.  
  372.                 if(!$inHandle)
  373.                         die("File '$filename' not found!");
  374.                
  375.                 $centralDir = $this->readCentralDir($inHandle, $filename);
  376.                
  377.                 $position = $centralDir['offset'];
  378.  
  379.                 for($i = 0; $i < $centralDir['entries']; $i++){
  380.                         fseek($inHandle, $position);
  381.                        
  382.                         $centralHeader = $this->readCentralFileHeader($inHandle);
  383.                        
  384.                         $position = ftell($inHandle);
  385.                        
  386.                         rewind($inHandle);
  387.                        
  388.                         fseek($inHandle, $centralHeader['offset']);
  389.                        
  390.                         if(in_array($i, $index) || sizeof($index) == 0){
  391.  
  392.                                 if($this->print){
  393.                                         print "Extract: " . $centralHeader['filename'] . "<br/>";
  394.                                         flush();
  395.                                 }
  396.  
  397.                                 if($centralHeader['external'] == 0x41FF0010 or $centralHeader['external'] == 16){
  398.                                         $this->buildDirectory($targetDir, $centralHeader['filename']);
  399.                                 }else{
  400.                                         $this->extractFile($targetDir, $inHandle);
  401.                                 }
  402.                         }
  403.                 }
  404.                 fclose($inHandle);
  405.         }
  406.        
  407.         function buildDirectory($baseDir, $path){
  408.                 $parts = explode("/", $path);
  409.                 $subDir = "";
  410.                
  411.                 foreach($parts as $part){
  412.                        
  413.                         if(!is_dir($baseDir . $subDir . $part))
  414.                                 mkdir($baseDir . $subDir . $part, 0755);
  415.                                
  416.                         $subDir .= $part . "/";
  417.                 }
  418.         }
  419.  
  420.         function _writeFile($inHandle, $outHandle, $fileSize, $gzRead = false){
  421.                 while($fileSize != 0){
  422.                         $stepSize = ($fileSize < 2048 ? $fileSize : 2048);
  423.                         fwrite($outHandle, pack('a' . $stepSize, $gzRead ? gzread($inHandle, $stepSize) : fread($inHandle, $stepSize)), $stepSize);
  424.                         $fileSize -= $stepSize;
  425.                 }
  426.         }
  427.  
  428.         function extractFile($targetDir, $inHandle){
  429.  
  430.                 $header = $this->readfileheader($inHandle);
  431.  
  432.                 $this->buildDirectory($targetDir, dirname($header['filename']));
  433.  
  434.                 $outHandle = fopen($targetDir . $header['filename'], 'wb');
  435.  
  436.                 if(!$outHandle){
  437.                         echo "Can not create '" . $targetDir . $header['filename'] . "' file !!!<br/>";
  438.                         return;
  439.                 }
  440.  
  441.                 $size = $header['compressed_size'];
  442.  
  443.         if($header['compression'] == 0){
  444.  
  445.                         $this->_writeFile($inHandle, $outHandle, $size);
  446.  
  447.         }else{
  448.        
  449.                 if(!$this->zlib)
  450.                         dir("ZLIB extension is needed to extract a compressed ZIP file!");
  451.  
  452.                 $tmpHandle = fopen($targetDir . $header['filename'] . '.gz', 'wb');
  453.  
  454.                 fwrite($tmpHandle, pack('va1a1Va1a1', 0x8b1f, Chr($header['compression']), Chr(0x00), time(), Chr(0x00), Chr(3)), 10);
  455.                        
  456.                         $this->_writeFile($inHandle, $tmpHandle, $size);
  457.  
  458.                 fwrite($tmpHandle, pack('VV', $header['crc'], $header['size']), 8);
  459.  
  460.                 fclose($tmpHandle);
  461.                
  462.                 $tmpHandle = gzopen($targetDir . $header['filename'] . '.gz', 'rb');
  463.                        
  464.                 $size = $header['size'];
  465.                        
  466.                         $this->_writeFile($tmpHandle, $outHandle, $size, true);
  467.  
  468.                 gzclose($tmpHandle);
  469.  
  470.                 unlink($targetDir . $header['filename'] . '.gz');
  471.         }
  472.  
  473.                 fclose($outHandle);
  474.                
  475.                 touch($targetDir . $header['filename'], $header['mtime']);
  476.                
  477.                 return true;
  478.         }
  479. }
  480. ?>

回复 "php压缩zip文件 zip压缩文件创建类"

这儿你可以回复上面这条便签

captcha