liunx下PHP压缩并规划目录结构zip文件

最近遇到一个项目需求, 要求把服务器上的一堆不按命名规则的图片文件压缩出来, 每个文件都要在压缩包里重新命名。
下面记录一下这个问题的解决:

———————————————————————————————————————

一、 服务器扩展ZipArchive

参考安装
在liunxde XSEHLL中输入

wget http://pecl.php.net/get/zip-1.8.3.tgz

自动下载到/root文件下了,也可移到etc文件下同一规范

然后执行在所在目录执行

tar -zxvf zip-1.8.3.tgz
cd zip-1.8.3

此时需要去寻找php-config 文件所在位置
可以输入find / -name php-config 寻找

输入,生成./configure 信息

phpize

注意

我的服务器上有phprize但是提示找不到,故可能是环境变量没配好
故输入export PATH=$PATH:/usr/local/php/bin

注意,最重要的一部,查看这个扩展的安装方式(一般不能通过下面这种方式安装的有readme.txt):

如果输入

./configure --with-php-config=/opt/remi/php56/root/usr/bin/php-config
不通过则不能使用./configure && make && make install安装,阅读readme.txt查看,如果是可执行文件则直接配置可执行文件到环境变量PATH

注意,./configure可能会提示找不到ZLIB, 不能成功编译

因为使用了函数 zlib 来支持数据压缩,因此需要安装 Zlib 模块

解决:本人是centos通过yum :yum install zlib zlib-devel
如果是ubuntu 则:通过sudo库
Complete!

接下来make 和make install还是出现问题,炸了,

注意,编译出现make: *** [php_zip.lo] Error

网上查了,要换个版本,emmmm
换成

wget http://pecl.php.net/get/zip-1.12.4.tg

以上操作再来一遍。

最后,终于成功

make install之后会出现一个zip.so保存的路径,这个路径要添加到php.ini里。

ok, 打开php.ini在“extension=”下面添加如下一段
extension=/opt/remi/php56/root/usr/lib64/php/modules/zip.so
zlib.output_compression = Off 改为 zlib.output_compression = On
zlib.output_compression_level 建议参数值是1~5

修改过后需要重启[php-fpm],如果你是编译安装的那么就用[绝对路径]去启动,如果是直接安装的可以用 service restart

重启apache。

二、PHP扩展类ZipArchive实现压缩解压Zip文件和文件打包下载

关于ZipArchive几点需要注意的地方:

1、打开的模式在linux下不可使用ZipArchive::OVERWRITE来自动创建ZIP包
2、如果要压缩的文件名包含中文,则不能识别,要通过iconv进行编码转化,并用file_exists检测
3、不能对压缩包进行二次压缩
4、PHP的readdir扫描要压缩的文件夹是不按顺序的,但都会扫描一次
5、估计有一个压缩处理池, 如果不close掉,那么这个处理池满了就压缩异常, 一个压缩对象最多处理压缩600个左右文件, 超过不报任何异常,不生成压缩包, 所以遇到大型的压缩项目, 分包压缩吧, 并在扫描文件时检测这个文件时第几个, 每600个文件close掉当前压缩包对象生成文件, 开始往新对象放入文件。

创建对象打开文件
//创建压缩包对象
$zip = new \ZipArchive();
$zipName = iconv("utf-8", "GB2312//IGNORE", C('UPLOAD_PATH').'/所有商品相册'.date('m-d', time()).'('.$i.').zip');
 //这里打开的模式在linux下不可使用ZipArchive::OVERWRITE来自动创建ZIP包
  $zip->open($zipName, \ZipArchive::CREATE);
批量对某个目录进行压缩
 /** 一次压缩
 * 将文件夹打包成zip文件 
 * add by guo 2018年6月3日
 * 循环的读取文件夹下的所有文件和文件夹
 * 其中$filename = readdir($handler)是每次循环的时候将读取的文件名赋值给$filename,
 * 为了不陷于死循环,所以还要让$filename !== false。
 * 定要用!==,因为如果某个文件名如果叫'0',或者某些被系统认为是代表false,用!=就会停止循环
 */
function addFileToZip($path, $zip , $goods_mod, $supplier ,$pre_dir , $goods_num) {
      //$zip为传入总共需要分包的压缩对象列表
    $handler = opendir($path); //打开当前文件夹由$path指定。
 
    while (($filename = readdir($handler)) !== false) {

    if ($filename != "." && $filename != "..") {//文件夹文件名字为'.'和‘..’,不要对他们进行操作
    if (is_dir($path . "/" . $filename)&&is_numeric($filename)) {// 如果读取的某个对象是文件夹,则递归

    //遇到商品id的文件夹把它替换成商品名,查找不到该商品则不递归该文件夹
    $where['goods_id'] = $filename;
    $where['supplier'] = $supplier;

    $goods_name = $goods_mod
    ->where($where)
    ->getField('goods_name',true);
    
    if(!empty($goods_name[0])){
        $goods_num++;
        //

addFileToZip($path . "/" . $filename, $zip, $goods_mod ,$supplier, $goods_name[0], $goods_num);//动态规划递归算法
    }

    } else { //将文件加入zip对象
    //对商品名中带/的进行转义
    //70个商品左右(500左右图片)达到可压缩最大值
    $pre_dir=str_replace("/","",$pre_dir);
    $package_div = ($goods_num/70);

    if (is_int($package_div)) { 
 //估计有一个压缩处理池, 如果不close掉,那么这个处理池满了就压缩异常
$zip[(int)$package_div-1]->close();
    }
        //$pre_dir用于命名这个文件存储的上级目录名字
    $zip[(int)$package_div]->addFile($path . "/" . $filename, $pre_dir.'/'.$filename);
    }
    }
    }
    
    closedir($path);

———————————————————————————————————————
由于不能二次压缩,所以以上的批量压缩算法会生成多个压缩包供前端下载。

你可能感兴趣的:(liunx下PHP压缩并规划目录结构zip文件)