PHP 的解压缩ZipArchive中的extractTo()方法 LINUX+nginx环境中解压zip时文件丢失的问题

本文介绍了解决在LINUX环境下使用ZipArchive解压包含汉字文件名的ZIP文件时遇到的问题。通过自定义解压流程,成功避免了文件名丢失的情况。

在项目中要用ZipArchive解压ZIP文件,起初测试环境在WINDOWS平台中,测试通过,换到 LINUX+nginx 的环境中时 就出问题了(ZIP包中有文件和文件夹一共3百多个文件,大部分是带汉字的文件名),问题的现象是:不带汉字的文件解压没有问题,另外有部分带汉字和数字字母的文件解压没有问题,然后其他纯文字的文件名就丢失了,也没有报错,最后把问题定位到了extractTo()方法,这个方法尼玛是个封装的方法,看不到实际的源代码。
      但是,发现 for($i = 0; $i < $zip->numFiles; $i++) 这里却可以找到所有的文件,个数是正常的,那么问题就出现解压后的 copy环节了。那么是不是可以借助这个循环自己解压,自己copy文件呢??

     于是   

    for($i = 0; $i < $zip->numFiles; $i++) {
       $filename = $zip->getNameIndex($i);

    if(!is_dir($filename)){
          copy("zip://".$path."#".$filename, $topath.$filename);
    }else{
         @mkdir($topath.'/'.$filename, 0777);
    }
   }   

  问题解决了哈。  找这个问题浪费了 我一天时间!! 希望对碰到同样 文件在解压的时候丢失的同学有帮助哈。 

function downloadRemoteFile($remoteUrl, $localPath) { try { // 初始化cURL会话 $ch = curl_init($remoteUrl); // 设置cURL选项 curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, // 返回内容作为字符串 CURLOPT_FOLLOWLOCATION => true, // 跟随重定向 CURLOPT_MAXREDIRS => 5, // 最大重定向次数 CURLOPT_CONNECTTIMEOUT => 15, // 连接超(秒) CURLOPT_TIMEOUT => 30, // 执行超(秒) CURLOPT_SSL_VERIFYPEER => false, // 禁用SSL验证(仅测试环境) CURLOPT_FAILONERROR => true, // 400+状态码视为错误 CURLOPT_HEADER => true, // 包含响应头 CURLOPT_NOBODY => false // 包含响应体 ]); // echo $ch; // 执行请求 $response = curl_exec($ch); // 检查cURL错误 if (curl_errno($ch)) { throw new Exception('cURL错误: ' . curl_error($ch)); } // 获取HTTP状态码 $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); $headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE); $headers = substr($response, 0, $headerSize); $body = substr($response, $headerSize); // 关闭cURL资源 curl_close($ch); // 处理HTTP状态码 if ($httpCode >= 400) { switch ($httpCode) { case 404: throw new Exception("远程文件不存在(404)"); case 403: throw new Exception("访问被拒绝(403)"); case 500: throw new Exception("服务器内部错误(500)"); default: throw new Exception("HTTP错误: $httpCode"); } } // 保存文件内容 if (file_put_contents($localPath, $body) === false) { throw new Exception("无法写入本地文件: $localPath"); } // 验证文件大小 $expectedSize = curl_getinfo($ch, CURLINFO_CONTENT_LENGTH_DOWNLOAD); $actualSize = filesize($localPath); if ($actualSize != $expectedSize) { unlink($localPath); // 删除不完整的文件 throw new Exception("文件大小不匹配: 预期 {$expectedSize}字节, 实际 {$actualSize}字节"); } return true; } catch (Exception $e) { // 错误日志记录 error_log("[".date('Y-m-d H:i:s')."] 下载失败: " . $e->getMessage()); return false; } } // 解压ZIP文件 function unzipFile($zipPath, $extractTo, $password = null) { // 验证文件存在 if (!file_exists($zipPath)) { throw new InvalidArgumentException("ZIP文件不存在: $zipPath"); } // 创建解压目录 if (!is_dir($extractTo) && !mkdir($extractTo, 0755, true)) { throw new RuntimeException("无法创建解压目录: $extractTo"); } $zip = new ZipArchive(); $flags = ZipArchive::CHECKCONS; // 尝试打开ZIP文件 if ($zip->open($zipPath, $flags) !== true) { throw new RuntimeException("无法打开ZIP文件: " . $zip->getStatusString()); } // 处理加密ZIP if ($password !== null) { if (!$zip->setPassword($password)) { $zip->close(); throw new RuntimeException("无法设置解压密码"); } } // 执行解压 if (!$zip->extractTo($extractTo)) { $error = $zip->getStatusString(); $zip->close(); throw new RuntimeException("解压失败: $error"); } $zip->close(); return true; } // 处理解压后的文件 function processExtractedFiles($directory, $callback) { if (!is_dir($directory)) { throw new InvalidArgumentException("目录不存在: $directory"); } $iterator = new RecursiveIteratorIterator( new RecursiveDirectoryIterator($directory, RecursiveDirectoryIterator::SKIP_DOTS), RecursiveIteratorIterator::SELF_FIRST ); $results = []; foreach ($iterator as $file) { if ($file->isFile()) { $results[] = call_user_func($callback, $file->getPathname()); } } return $results; } $remoteUrl = 'http://10.69.5.114:8088/Tool-IT/自动排产系统1.5.4.zip'; $remoteUrlEncoded = urlencode($remoteUrl); $localFile = __DIR__ . '/' . $response['data']['filename']; // 1. 下载远程ZIP文件 echo "开始下载文件...\n"; if (downloadRemoteFile($remoteUrl, $localFile)) { echo "文件下载成功!"; // 后续解压操作 $zip = new ZipArchive; if ($zip->open($localFile) === TRUE) { $zip->extractTo(__DIR__); $zip->close(); echo "解压完成!"; } else { echo "ZIP文件解压失败"; } } else { echo "文件下载失败,请检查错误日志"; } echo "\n下载完成! 文件保存至: $localZip\n\n";开始下载文件... 文件下载成功!<br /> <b>Fatal error</b>: Uncaught Error: Class "ZipArchive" not found in D:\laragon\www\version.php:190 Stack trace: #0 {main} thrown in <b>D:\laragon\www\version.php</b> on line <b>190</b><br />
最新发布
08-19
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值