【问题标题】:PHP ZipArchive file permissionsPHP ZipArchive 文件权限
【发布时间】:2016-07-17 04:48:53
【问题描述】:

当我使用 PHP ZipArchive 对象制作 ZIP 存档时,存档中的所有文件都将权限设置为 666,尽管原始文件的权限设置为 644。

我的脚本正确地制作了 zip 存档,只是权限混乱了。

////// Make Template archive object
$templateArchive = new ZipArchive();
$templateArchive->open(PATH_TO_TEMPLATES.'_files/'.$templateName.'/_pack/'.$templateName.'.zip', ZipArchive::CREATE | ZipArchive::OVERWRITE);

$files = new RecursiveIteratorIterator(
    new RecursiveDirectoryIterator($templateDir."/templates/".$template_archive_name),
    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();

        // relative path is full path, reduced with length of templateDir string and 11 more chars for /templates/
        $relativePath = substr($filePath, strlen($templateDir) + 11);

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

// Template Zip archive will be created only after closing object
$templateArchive->close();

附:我在 Mac 上使用 MAMP。我刚刚发现只有在选择 PHP 5.6.10 版本时才会出现这个问题。当我选择5.5.26时,文件的权限是正确的。

【问题讨论】:

标签: php zip


【解决方案1】:

您可以通过在ZipArchive::addFile() 语句后添加以下代码来保留存档文件中的 Unix 权限:

$templateArchive->setExternalAttributesName($relativePath,
                                            ZipArchive::OPSYS_UNIX,
                                            fileperms($filePath) << 16);

这会使用实际文件的权限更新 $filePath 条目的外部属性。

Unix 权限可以存储在 ZIP 文件中的每个条目的外部属性中,但您必须在外部属性的正确位置使用 shift 16 bits to store the permissions,这就是为什么 &lt;&lt; 16 应用于 fileperms($filePath) 的输出。

ZipArchive::setExternalAttributesName() 的文档也有一个例子,它具有 Unix 权限设置:https://secure.php.net/manual/en/ziparchive.setexternalattributesname.php

至于目录的权限,您需要使用ZipArchive::addEmptyDir() 添加目录(因为ZipArchive::addFile() on a directory will result in an error),然后使用ZipArchive::setExternalAttributesName() 应用与常规文件相同的权限。

由于RecursiveDirectoryIterator 的工作方式,当前目录名称将以/. 结尾,并且由于ZipArchive::addEmptyDir() 的工作方式,存储的目录将以/ 结尾。要申请ZipArchive::setExternalAttributesName(),您必须提供准确的条目名称,因此我建议在这两种方法中去掉尾随点。

这是您编辑的代码以支持保留文件和目录的权限:

////// Make Template archive object
$templateArchive = new ZipArchive();
$templateArchive->open(PATH_TO_TEMPLATES.'_files/'.$templateName.'/_pack/'.$templateName.'.zip', ZipArchive::CREATE | ZipArchive::OVERWRITE);

$files = new RecursiveIteratorIterator(
        new RecursiveDirectoryIterator($templateDir."/templates/".$template_archive_name),
        RecursiveIteratorIterator::LEAVES_ONLY
);      

foreach ($files as $name => $file)
{               

        // Get real and relative path for current file
        $filePath = $file->getRealPath();

        // relative path is full path, reduced with length of templateDir string and 11 more chars for /templates/
        $relativePath = substr($filePath, strlen($templateDir) + 11);

        // Add regular files
        if (!$file->isDir())
        {
                // Add current file to archive
                $templateArchive->addFile($filePath, $relativePath);
        }
        elseif (substr($relativePath, -2) === "/.")
        {
                // Remove the dot representing the current directory
                $relativePath = substr($relativePath, 0, -1);
                // Add current directory to archive
                $templateArchive->addEmptyDir($relativePath);
        }
        else
        {
                continue;
        }

        $templateArchive->setExternalAttributesName($relativePath,
                ZipArchive::OPSYS_UNIX,
                fileperms($filePath) << 16);
}

// Template Zip archive will be created only after closing object
$templateArchive->close();

【讨论】:

  • 感谢您的建议!我在 addFile 语句之后添加了这个,但是,在 Unix 主机上解压缩后,文件仍然是 CHMOD 666。我在 Mac (MAMP) 上运行 PHP 脚本。我不确定这是否有什么不同。
  • @MilosStankovic:当您检查生成的 ZIP 文件时,权限是否正确?您可以通过将 ZIP 文件作为第一个参数运行 zipinfo 命令来查看权限。如果权限正确,说明解压过程忽略了权限。
  • 当我运行这个命令时,我得到了存档文件的完整列表和每个文件的权限设置为 666 的信息,例如:-rw-rw-rw- 6.3 unx 31 b- defX 14- Oct-01 15:52 media/media/js/index.html 最初,文件权限为 644,当我使用 PHP 5.6 或更早版本制作档案时,权限不变。
  • @MilosStankovic:接下来要检查的是fileperms($filePath) 是否实际上返回了正确的权限。如果您的输入文件具有 0644 权限,您应该将 33188 作为整数(八进制的100644)。
  • 我添加了一行:echo substr(sprintf('%o', fileperms($filePath)), -4);之后:$templateArchive->addFile($filePath, $relativePath);并获得正确的权限,所有文件的权限为 0644,ZIP 存档中包含的所有目录的权限为 0755。但是,当我将该 ZIP 上传到 Unix 主机并解压缩时,所有文件的权限为 0666,所有文件夹的权限为 0755。
猜你喜欢
  • 2020-09-05
  • 1970-01-01
  • 2018-11-01
  • 2011-04-21
  • 2014-10-26
  • 2011-10-14
  • 2011-05-27
  • 2010-09-28
相关资源
最近更新 更多