【问题标题】:Warning: ZipArchive::close(): Failure to create temporary file: Unknown error警告:ZipArchive::close():创建临时文件失败:未知错误
【发布时间】:2021-11-03 21:07:08
【问题描述】:

我在 PHP 中有一个奇怪的错误,我遍历了很多目录并通过压缩文件夹来归档旧的东西,然后删除该文件夹及其所有文件。这在大多数情况下都可以正常工作,但是对于一些条目,我会收到此错误:

警告:ZipArchive::close():未能创建临时文件: 中的未知错误 myfile.php 上 第 132 行

我有这个 PHP 代码,直接取自 https://stackoverflow.com/a/4914807/2028935,但我插入了 exit() 以确保捕获错误:

// Get real path for our folder
$rootPath = realpath("/myfolder/pathX");

// Initialize archive object
$zip = new ZipArchive();
$zip->open("/myfolder/myfile.zip", ZipArchive::CREATE | ZipArchive::OVERWRITE);

// Create recursive directory iterator
/** @var SplFileInfo[] $files */
$files = new RecursiveIteratorIterator(
    new RecursiveDirectoryIterator($rootPath),
    RecursiveIteratorIterator::LEAVES_ONLY
);

foreach ($files as $name => $file) {
    // Skip directories (they would be added automatically)
    if (!$file->isDir()) {
        // Get real and relative path for current file
        $filePath = $file->getRealPath();
        $relativePath = substr($filePath, strlen($rootPath) + 1);

        // Add current file to archive
        $zip->addFile($filePath, $relativePath);
    }
}

// Zip archive will be created only after closing object
if(!$zip->close()) {
    exit();
}

错误在 132 行触发,即这一行,if(!$zip->close()) {

我没有文件夹或文件权限问题,因为文件夹和文件确实被删除了(另一个代码),但我无法弄清楚 ZIP 中的 Unknown error 是什么?

我在 Windows 服务器上使用 PHP 7.4。

### 更新###

似乎未知错误是由于ZIP文件路径太长,但我不明白为什么。如果$zip->open("/myfolder/myfile.zip", ZipArchive::CREATE | ZipArchive::OVERWRITE);中的路径长于或等于250个字符,那么就会出现这个错误!?

我可以理解是否会有 256 或 260 个字符的限制,我可以看到那里可能有一些限制,但为什么是 250?

目前我正在研究是否可以通过使用 DOS 命令SUBST 或通过注册表HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\DOS Devices 进行本地驱动器/文件夹映射来减少路径长度

【问题讨论】:

  • 发生在哪一行?
  • 更新后的帖子 - 在if(!$zip->close()) {
  • 发生“少数条目”是什么意思?如果它在您关闭 zip 文件时发生,您如何知道它发生在哪些条目上?
  • 因为压缩只是代码的一部分。我浏览了一个目录列表。我可以看到失败的条目上描述的错误。

标签: php zip


【解决方案1】:

经过更多分析,我发现Unknown error 是由于 ZIP 文件路径太长 - 它超过了 250 个字符,这似乎是 Windows 的限制,虽然我看到了此限制的波动数字,从 247 到 260。

我尝试过的一个可能的解决方案是在 DOS 命令中执行 SUBST 命令,该命令为长路径创建驱动器 - 就像这样 subst O: D:\very\long\..\path。这将提供一个 O:\ 我可以直接连接的位置,但这仅适用于我的本地用户帐户,也无法在重新启动后继续存在。

我发现有效的解决方案是在注册表中向HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\DOS Devices 添加一个新的REG_SZ。我添加了这个REG_SZ(字符串):

O: => \DosDevices\D:\very\long...\path

重启 Windows Server (2019) 后,我现在有了 O-drive,我可以在 IIS(以及 PHP)中使用它,我的问题已经解决了 :-)

【讨论】:

    猜你喜欢
    • 2017-04-15
    • 2018-11-01
    • 1970-01-01
    • 2017-10-06
    • 2013-08-26
    • 2018-09-03
    • 1970-01-01
    • 1970-01-01
    • 2020-01-27
    相关资源
    最近更新 更多