(前面我写个只压缩文件夹内文件,不带子文件夹的方法。后面我补充了个加强版,可以压缩文件夹里面的文件和子文件夹,可以耐心看下去)
↓↓↓这个链接是整理版↓↓↓,只贴出了最新改进后的方法和特点
http://blog.csdn.net/qq_29238009/article/details/79063894
这里下面的都是一些写的时候的思路,需要直接用的看↑这个链接,想知道每次修改的解题思路的看↓的文章
前言:
一般来说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);
注: