PHP 压缩文件生成zip(解决中文文件名问题)

来源:互联网 发布:java 解压jar包命令 编辑:程序博客网 时间:2024/05/22 05:08

前言:

一般来说PHP压缩文件,如果没有额外置入其他插件的话,普遍是使用ZipArchive的。
在网上一般来说搜索是能搜索得到各种压缩的算法,但是我发现了他们都不能压缩进中文名称的文件,即使是各种修改字符编码都没有,然后我在多次试验后,突然发现了ZipArchive还有个小“漏洞”能利用~于是就成功压缩进中文名称的文件啦。

需求:

现在一个文件夹内有一堆格式文件,然后需要将目录下的文件压缩进一个zip里面,然后返回下载。

已知小“漏洞”:

ZipArchive的所有方法,不支持输入中文(各种字符编码),但是能够在成功addFile后使用renameName,这个重命名方法是支持输入中文的。意思就是我们能在文件已经在zip的情况后,在里面更改文件的名字,将英文数字文件名改成中文文件名。

解题思路:

(1)将文件夹内的所有文件名(例如 中文.txt),改名成为其他文件名(除中文外,例如1.txt),并且保存好对应关系,并且保存好对应关系,并且保存好对应关系(重要事情说三遍)。
(2)将改名后的文件添加进ZipArchive中。
(3)利用(1)中保留的名称对应关系,将ZipArchive中的文件名更改回正确的中文名,然后$zip->close()。
(4)将文件夹中的所有文件名根据(1)中的对应关系更改回来。(3、4步骤不能调换!zip close之前,目录下的文件名要和add的时候一致,不然就找不到文件了)

源码:

function zipDir($basePath,$zipName){    $zip = new ZipArchive();    $fileArr = [];    $fileNum = 0;    if (is_dir($basePath)){        if ($dh = opendir($basePath)){            $zip->open($zipName,ZipArchive::CREATE);            while (($file = readdir($dh)) !== false){                if(in_array($file,['.','..',])) continue; //无效文件,重来                $file = iconv('gbk','utf-8',$file);                $extension = strchr($file,'.');                rename(iconv('UTF-8','GBK',$basePath.'\\'.$file), iconv('UTF-8','GBK',$basePath.'\\'.$fileNum.$extension));                $zip->addFile($basePath.'\\'.$fileNum.$extension,$fileNum.$extension);                $zip->renameName($fileNum.$extension,$file);                $fileArr[$fileNum.$extension] = $file;                $fileNum++;            }            $zip->close();            closedir($dh);            foreach($fileArr as $k=>$v){                rename(iconv('UTF-8','GBK',$basePath.'\\'.$k), iconv('UTF-8','GBK',$basePath.'\\'.$v));            }        }    }}

使用:

$basePath = storage_path('excel');    $zipName = storage_path('test.zip');    zipDir($basePath,$zipName);

注:
1.我是在wamp+laravel下做的,其他环境和框架请自行调整下吧,反正php都是一样的
2.这里我保存文件名对应关系是用array数组。你也可以先跑一遍目录,将对应关系先写进一个文件中;再跑一遍,将文件名都改了;再执行上面的代码(当然需要微调下代码)。这样安全性就高点,不怕中途各种原因(断电?服务器突然崩了?)导致你不知道哪个文件原来的名字是什么,还能找到对应关系的文件手工改回来
3.上面压缩的是一个目录下全部都是文件,没有子目录。我暂时先写到这里,过会有时间我再把递归子目录的方法加上来,反正解决了这个中文问题其他的就好办了,这个递归子目录的方法网上也挺多的,先mark一下(todo)

阅读全文
0 0