php版本:PHP 5.6.28
原来的解压代码:
$zip = new ZipArchive();
$flag = $zip->open($filePath);
if ($flag !== true) {
return $retJson;
}
$zip->extractTo($extractPath);
$zip->close();
如果zip文件含有文件名是B1+1231+伊利.jpg类似的文件,解压出来是B1+1231+?i?ة???.jpg 这样的乱码
解决方法1,适用于php7.x版本。
重点在$statInfo = $zip->statIndex($i,\ZipArchive::FL_ENC_RAW);这行代码上。
<?php
function extractZipToFile($zipName,$dir){
$zip = new \ZipArchive;
if ($zip->open($zipName) === TRUE) {
if(!is_dir($dir)) mkdir($dir,0775,true);
$docnum = $zip->numFiles;
for($i = 0; $i < $docnum; $i++) {
$statInfo = $zip->statIndex($i,\ZipArchive::FL_ENC_RAW);
//$statInfo = $zip->statIndex($i);
$filename = transcoding2($statInfo['name']);
echo $filename . "\n";
if($statInfo['crc'] == 0) {
//新建目录
if(!is_dir($dir.'/'.substr($filename, 0,-1))) mkdir($dir.'/'.substr($filename, 0,-1),0775,true);
} else {
//拷贝文件
copy('zip://'.$zipName.'#'.$zip->getNameIndex($i), $dir.'/'.$filename);
}
}
$zip->close();
return true;
}else{
return false;
}
}
function transcoding2($fileName){
return iconv('UTF-8', 'GBK', $fileName);
}
function transcoding($fileName){
$encoding = mb_detect_encoding($fileName,['UTF-8','GBK','BIG5','CP936']);
if (DIRECTORY_SEPARATOR == '/'){ //linux
$filename = iconv($encoding,'UTF-8',$fileName);
}else{ //win
$filename = iconv($encoding,'GBK',$fileName);
}
return $filename;
}
extractZipToFile("fuzhou_zw.zip", "/home/vv/facemng/dest")
?>
解决方法2:使用pclzip.lib.php,但是要做点改造。适用php5.6+版本
function unzipFile($zipFile, $extractPath) {
global $cLog;
$archive = new PclZip($zipFile);
$list = $archive->extract(PCLZIP_OPT_PATH, $extractPath);
$cLog->TRACE("extract list=" . json_encode($list));
return;
}
改造的代码,增加了编码转换
public function privExtractFile(&$p_entry, $p_path, $p_remove_path, $p_remove_all_path, &$p_options)
{
// ----- Add the path
if ($p_path != '') {
$encode = mb_detect_encoding($p_entry['filename'], array("ASCII", 'UTF-8', "GB2312", "GBK", 'BIG5'));
if ($encode != "UTF-8") {
$p_entry['filename'] = mb_convert_encoding($p_entry['filename'], 'UTF-8', 'gb2312');
}
$p_entry['filename'] = $p_path."/".$p_entry['filename'];
}
}
解决方法3:调用python代码
单独在php中可以试验成功,但是放在项目中失败。报错:
“UnicodeEncodeError: ‘ascii’ codec can’t encode characters in position 41-42: ordinal not in range(128)”
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# unzip.py
import os
import sys
import zipfile
import codecs
def unzip_file(zip_file_name, target_path):
# print "Processing File " + sys.argv[1]
# print "target path " + sys.argv[2]
if not os.path.exists(target_path) and target_path != "":
os.makedirs(target_path)
file = zipfile.ZipFile(zip_file_name, "r")
for name in file.namelist():
utf8name = name.decode('gbk')
# print "Extracting " + utf8name
data = file.read(name)
fo = codecs.open(target_path + utf8name, "w+b")
fo.write(data)
fo.close()
file.close()
return 0
if __name__ == '__main__':
unzip_file(sys.argv[1], sys.argv[2] + "/")
解决方法4:调用unzip命令解压
在单独的php文件中可以成功,放在项目中失败
unzip -O CP936 xxx.zip (用GBK, GB18030也可以)