php生成zip压缩文件的方法详解


Posted in PHP onJune 09, 2013
require_once "./include/zip.php"; 
$zip = new PHPZip(); 
//$zip -> createZip("要压缩的文件夹目录地址", "压缩后的文件名.zip"); //只生成不自动下载 
$zip -> downloadZip("要压缩的文件夹目录地址", "压缩后的文件名.zip");
//自动下载

实例:可以参考下面的伪代码来看一个具体的使用场景:
代码
require_once "./include/zip.php"; 
if (!$download) { 
exit(); 
} 
set_time_limit(60); 
$tmpManager = new TmpManager(); //假设我们有一个类来完成后面的操作 
$tempfolder = array(); 
$tempfile = array(); 
//假设我们是通过在页面上选择checkbox来下载已选的文件夹或文件,并一同打包 
for($i = 0;$i < $checkboxnum;$i++) { 
$value = ${"select".$i}; 
if ($value != '') { 
$this_type = substr($value, 0, 1); 
$this_id = substr($value, 1); 
//将文件夹和文件的情况分开处理 
if ($this_type == 'd') { 
$tempfolder[] = $this_id; 
} 
elseif ($this_type == 'f') { 
$tempfile[] = $this_id; 
} 
} 
} 
@mkdir($tempdir); 
$curtempdir = "$tempdir/".$userid; //不同用户在不同的临时文件夹下操作 
if (file_exists($curtempdir)) { 
$tmpManager->DeleteDir($curtempdir); //删除旧的文件夹 
} 
if (sizeof($tempfolder) > 0 || sizeof($tempfile) > 0) { 
mkdir($curtempdir, 0777); //如果有要打包的文件货文件夹,重新创建文件夹 
} 
if (sizeof($tempfile) > 0) { 
$tmpManager->CopyFile($tempfile,$curtempdir); //将要下载的文件copy到创建的文件夹 
} 
if (sizeof($tempfolder) > 0) { 
$tmpManager->CopyFolder($tempfolder,$curtempdir); //将要下载的文件夹copy到创建的文件夹 
} 
$zip = new PHPZip(); 
$zip -> downloadZip($curtempdir, "file_".date('Ymd').".zip"); //打包并下载

zip.php
<?php 
/* 
File name: /include/zip.php 
Author: Horace 2009/04/15 
*/ 
class PHPZip{ 
var $dirInfo = array("0","0"); 
var $rootDir = ''; 
var $datasec = array(); 
var $ctrl_dir = array(); 
var $eof_ctrl_dir = "/x50/x4b/x05/x06/x00/x00/x00/x00"; 
var $old_offset = 0; 
function downloadZip(){ 
createZip($dir, $zipfilename, true); 
} 
function createZip($dir, $zipfilename, $autoDownload = false){ 
if (@function_exists('gzcompress')){ 
@set_time_limit("0"); 
if (is_array($dir)){ 
$fd = fopen ($dir, "r"); 
$fileValue = fread ($fd, filesize ($filename)); 
fclose ($fd); 
if (is_array($dir)) $filename = basename($dir); 
$this -> addFile($fileValue, "$filename"); 
}else{ 
$this->dirTree($dir,$dir); 
} 
$zipfilenametemp = time().$zipfilename; 
$out = $this -> filezip(); 
$fp = fopen($zipfilenametemp, "w"); 
fwrite($fp, $out, strlen($out)); 
fclose($fp); 
$filesize = filesize($zipfilenametemp); 
if ($filesize < 104857600) { 
if($autoDownload){ 
header("Content-type: application/octet-stream"); 
header("Content-disposition: attachment; filename=".$zipfilename); 
} 
echo $this -> filezip(); 
}else{ 
echo "create zip error!"; 
} 
unlink($zipfilenametemp); 
} 
} 
//get dir tree.. 
function dirTree($directory,$rootDir){ 
global $_SERVER,$dirInfo,$rootDir; 
$fileDir=$rootDir; 
$myDir=dir($directory); 
while($file=$myDir->read()){ 
if(is_dir("$directory/$file") and $file!="." and $file!=".."){ 
$dirInfo[0]++; 
$rootDir ="$fileDir$file/"; 
$this -> addFile('', "$rootDir"); 
//go on n's folders 
$this->dirTree("$directory/$file",$rootDir); 
}else{ 
if($file!="." and $file!=".."){ 
$dirInfo[1]++; 
//$fd = fopen ("$directory/$file", "r"); 
$fileValue = file_get_contents("$directory/$file"); 
//fclose ($fd); 
$this -> addFile($fileValue, "$fileDir$file"); 
} 
} 
} 
$myDir->close(); 
} 
function unix2DosTime($unixtime = 0) { 
$timearray = ($unixtime == 0) ? getdate() : getdate($unixtime); 
if ($timearray['year'] < 1980) { 
$timearray['year'] = 1980; 
$timearray['mon'] = 1; 
$timearray['mday'] = 1; 
$timearray['hours'] = 0; 
$timearray['minutes'] = 0; 
$timearray['seconds'] = 0; 
} // end if 
return (($timearray['year'] - 1980) << 25) | ($timearray['mon'] << 21) | ($timearray['mday'] << 16) | 
($timearray['hours'] << 11) | ($timearray['minutes'] << 5) | ($timearray['seconds'] >> 1); 
} 
function addFile($data, $name, $time = 0){ 
$name = str_replace('//', '/', $name); 
$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"; // ver needed to extract 
$fr .= "/x00/x00"; // gen purpose bit flag 
$fr .= "/x08/x00"; // compression method 
$fr .= $hexdtime; // last mod time and date 
// "local file header" segment 
$unc_len = strlen($data); 
$crc = crc32($data); 
$zdata = gzcompress($data); 
$c_len = strlen($zdata); 
$zdata = substr(substr($zdata, 0, strlen($zdata) - 4), 2); // fix crc bug 
$fr .= pack('V', $crc); // crc32 
$fr .= pack('V', $c_len); // compressed filesize 
$fr .= pack('V', $unc_len); // uncompressed filesize 
$fr .= pack('v', strlen($name)); // length of filename 
$fr .= pack('v', 0); // extra field length 
$fr .= $name; 
// "file data" segment 
$fr .= $zdata; 
// "data descriptor" segment (optional but necessary if archive is not 
// served as file) 
$fr .= pack('V', $crc); // crc32 
$fr .= pack('V', $c_len); // compressed filesize 
$fr .= pack('V', $unc_len); // uncompressed filesize 
// add this entry to array 
$this -> datasec[] = $fr; 
$new_offset = strlen(implode('', $this->datasec)); 
// now add to central directory record 
$cdrec = "/x50/x4b/x01/x02"; 
$cdrec .= "/x00/x00"; // version made by 
$cdrec .= "/x14/x00"; // version needed to extract 
$cdrec .= "/x00/x00"; // gen purpose bit flag 
$cdrec .= "/x08/x00"; // compression method 
$cdrec .= $hexdtime; // last mod time & date 
$cdrec .= pack('V', $crc); // crc32 
$cdrec .= pack('V', $c_len); // compressed filesize 
$cdrec .= pack('V', $unc_len); // uncompressed filesize 
$cdrec .= pack('v', strlen($name) ); // length of filename 
$cdrec .= pack('v', 0 ); // extra field length 
$cdrec .= pack('v', 0 ); // file comment length 
$cdrec .= pack('v', 0 ); // disk number start 
$cdrec .= pack('v', 0 ); // internal file attributes 
$cdrec .= pack('V', 32 ); // external file attributes - 'archive' bit set 
$cdrec .= pack('V', $this -> old_offset ); // relative offset of local header 
$this -> old_offset = $new_offset; 
$cdrec .= $name; 
// optional extra field, file comment goes here 
// save to central directory 
$this -> ctrl_dir[] = $cdrec; 
} 
function filezip(){ 
$data = implode('', $this -> datasec); 
$ctrldir = implode('', $this -> ctrl_dir); 
return 
$data . 
$ctrldir . 
$this -> eof_ctrl_dir . 
pack('v', sizeof($this -> ctrl_dir)) . // total # of entries "on this disk" 
pack('v', sizeof($this -> ctrl_dir)) . // total # of entries overall 
pack('V', strlen($ctrldir)) . // size of central dir 
pack('V', strlen($data)) . // offset to start of central dir 
"/x00/x00"; // .zip file comment length 
} 
} 
?>

PHP 相关文章推荐
JAVA/JSP学习系列之四
Oct 09 PHP
sphinx增量索引的一个问题
Jun 14 PHP
PHP和Mysqlweb应用开发核心技术 第1部分 Php基础-3 代码组织和重用2
Jul 03 PHP
PHP输入流php://input介绍
Sep 18 PHP
PHP中__get()和__set()的用法实例详解
Jun 04 PHP
解析centos中Apache、php、mysql 默认安装路径
Jun 25 PHP
php中用memcached实现页面防刷新功能
Aug 19 PHP
thinkphp3.0输出重复两次的解决方法
Dec 19 PHP
php中mysql操作buffer用法详解
Mar 19 PHP
PHP数据库操作三:redis用法分析
Aug 16 PHP
PHP fprintf()函数用法讲解
Feb 16 PHP
php 使用expat方式解析xml文件操作示例
Nov 26 PHP
基于php iconv函数的使用详解
Jun 09 #PHP
PHP页面间参数传递的四种方法详解
Jun 09 #PHP
利用PHP+JS实现搜索自动提示(实例)
Jun 09 #PHP
深入php处理整数函数的详解
Jun 09 #PHP
解决ajax+php中文乱码的方法详解
Jun 09 #PHP
PHP写的加密函数,支持私人密钥(详细介绍)
Jun 09 #PHP
PHP版 汉字转码的实现详解
Jun 09 #PHP
You might like
php时间不正确的解决方法
2008/04/09 PHP
php 自写函数代码 获取关键字 去超链接
2010/02/08 PHP
php计算指定目录下文件占用空间的方法
2015/03/13 PHP
PHP date函数常用时间处理方法
2015/05/11 PHP
从零开始学习jQuery (八) 插播:jQuery实施方案
2011/02/23 Javascript
javascript 学习笔记(一)DOM基本操作
2011/04/08 Javascript
jQuery-serialize()输出序列化form表单值的方法
2012/12/26 Javascript
js获取事件源及触发该事件的对象
2013/10/24 Javascript
jQuery替换字符串(实例代码)
2013/11/13 Javascript
jquery插件jquery.LightBox.js实现点击放大图片并左右点击切换效果(附demo源码下载)
2016/02/25 Javascript
JavaScript入门教程之引用类型
2016/05/04 Javascript
html+js实现简单的计算器代码(加减乘除)
2016/07/12 Javascript
浅谈Javascript数据属性与访问器属性
2016/07/26 Javascript
jQuery和CSS仿京东仿淘宝列表导航菜单
2017/01/04 Javascript
Angular4开发解决跨域问题详解
2017/08/28 Javascript
JS脚本加载后执行相应回调函数的操作方法
2018/02/28 Javascript
4 种滚动吸顶实现方式的比较
2019/04/09 Javascript
Webpack按需加载打包chunk命名的方法
2019/09/22 Javascript
原生JS实现萤火虫效果
2020/03/07 Javascript
微信小程序实现点击导航条切换页面
2020/11/19 Javascript
[14:24]Optic Gaming vs PSG LGD BO3
2018/06/07 DOTA
python进阶教程之词典、字典、dict
2014/08/29 Python
Python基于回溯法子集树模板实现8皇后问题
2017/09/01 Python
Python SqlAlchemy动态添加数据表字段实例解析
2018/02/07 Python
Pytorch之view及view_as使用详解
2019/12/31 Python
python脚本监控logstash进程并邮件告警实例
2020/04/28 Python
python报错: 'list' object has no attribute 'shape'的解决
2020/07/15 Python
英国现代、当代和设计师家具店:Furntastic
2020/07/18 全球购物
我为自己代言广告词
2014/03/18 职场文书
书香校园建设方案
2014/05/02 职场文书
公司搬迁通知
2015/04/20 职场文书
2015初中团支部工作总结
2015/07/21 职场文书
大学生安全教育主题班会
2015/08/12 职场文书
分家协议书范本
2016/03/22 职场文书
动作冒险《Hell Is Us》将采用虚幻5 消灭怪物探索王国
2022/04/13 其他游戏
centos环境下nginx高可用集群的搭建指南
2022/07/23 Servers