PHP ZipArchive::addGlob()执行缓慢,临时目录提前删除问题问询
问题
我有一段代码,执行流程如下:
- 生成CSV文件到临时目录;
- 调用
ZipArchive::addGlob()方法; - 删除临时目录。
但ZipArchive::addGlob()执行速度过慢,导致文件在压缩完成前就被删除。代码示例如下:
function saveCsvDaysDataZip($campaign_id) { $tempDirName = CampaignsDeviceDays::CSV_REPORTS_DIR . '/' . $campaign_id . '/temp'; $zip = new ZipArchive(); $zip->open($tempDirName . 'reports.zip', ZipArchive::CREATE | ZipArchive::OVERWRITE); $addGlob = $zip->addGlob("$tempDirName/*", GLOB_BRACE, ['remove_all_path' => TRUE]); if( $addGlob === false ) throw new \Exception("CampaignsDeviceDays::saveCsvDaysDataZip() error: \$zip->addGlobe() failed. " . $this->zipArchive->getStatusString() ); } public function removeCsvExportsDir($campaign_id) { $dirName = self::CSV_REPORTS_DIR . '/' . $campaign_id . '/temp'; FileSystem::delete($dirName); } $saveCsvDaysDataZip($campaign_id); $removeCsvExportsDir($campaign_id);
请问是否存在removeCsvExportsDir($campaign_id)在addGlob()执行完成前就被调用的可能?
回答
不存在这种可能。
PHP是同步执行的语言,代码会严格按从上到下的顺序逐行执行:只有当saveCsvDaysDataZip()函数完全执行完毕(包括addGlob()方法执行完成),才会继续调用removeCsvExportsDir()。
你遇到的问题,根源是ZipArchive的延迟写入机制:addGlob()只是将文件加入压缩队列,实际的压缩写入操作要等到ZipArchive::close()调用时才会完成。你的代码里缺少了$zip->close()这一步,导致临时目录被删除时,压缩进程还没完成对CSV文件的读取,最终引发错误。
修复方案
在saveCsvDaysDataZip()函数中,调用完addGlob()后必须关闭ZipArchive实例,确保所有压缩操作完成:
function saveCsvDaysDataZip($campaign_id) { $tempDirName = CampaignsDeviceDays::CSV_REPORTS_DIR . '/' . $campaign_id . '/temp'; $zip = new ZipArchive(); $zip->open($tempDirName . 'reports.zip', ZipArchive::CREATE | ZipArchive::OVERWRITE); $addGlob = $zip->addGlob("$tempDirName/*", GLOB_BRACE, ['remove_all_path' => TRUE]); if( $addGlob === false ) { $zip->close(); // 出错时也要关闭资源 throw new \Exception("CampaignsDeviceDays::saveCsvDaysDataZip() error: \$zip->addGlob() failed. " . $zip->getStatusString() ); } // 关键:关闭ZipArchive,确保所有压缩写入操作完成 $zip->close(); }
这样就能保证压缩操作全部结束后,才会执行后续的目录删除操作,避免文件读取异常。
内容的提问来源于stack exchange,提问作者Čamo
相关产品推荐
相关产品推荐

