警告:ZipArchive::close():创建临时文件失败:未知错误

问题描述 投票:0回答:2

我在 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 Server 上使用 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

php zip
2个回答
0
投票

经过更多分析,我发现

Unknown error
是由于 ZIP 文件路径太长 - 它长于 250 个字符,这似乎是 Windows 限制,尽管我看到此限制上的数字波动,任何东西从 247 到 260。

我尝试过的一个可能的解决方案是在 DOS 命令中执行

SUBST
命令,该命令为长路径创建一个驱动器 - 就像这样
subst O: D:\very\long\..\path
。这将给出一个
O:\
,我可以直接连接,但这仅适用于我的本地用户帐户,也无法在重新启动后继续存在。

我发现有效的解决方案是在注册表中向

REG_SZ
添加新的
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\DOS Devices
。我添加了这个
REG_SZ
(字符串):

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

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


0
投票

在我的例子中,我执行的用户没有目录的访问权限:

  1. 通过终端检查您想要更改的目录的访问权限和所有者:
# ls -ld foo
drwxrwxr-x 4 root root 4096 Apr 11 14:40 foo
  1. 通过将

    $user = posix_getpwuid(posix_geteuid())['name'];
    添加到脚本中来检查运行 php 脚本的用户。

  2. 在我的例子中,脚本是通过

    www-data
    用户执行的,因此我将目录的所有权更改为
    www-data
    :

chown -R www-data:www-data foo

这解决了我的问题。

(如果您因为安全原因认为这不好,可以通过评论联系我根据反馈编辑答案)

© www.soinside.com 2019 - 2024. All rights reserved.