使用 PHP 7.4 在 ZipArchive 中设置目录 mtime

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

在 PHP 7.4 中,

ZipArchive::setMtimeIndex
ZipArchive::setMtimeName
都不可用。

在 PHP 7.4 中从文件创建 Zip 存档时;文件的

mtime
和权限通过
ZipArchive::addFile
方法应用于相应的 Zip 条目的属性。

不幸的是,目录并非如此;因为它们是使用

ZipArchive::addEmptyDir
方法创建的,而不是从文件系统读取。

我创建了一个

fixDirAttributes
函数来修复 Zip 存档中目录的
mtime
和权限。但这不能与 PHP 7.4 一起使用。

您知道在 PHP 7.4 中修复 Zip 存档目录的

mtime
的方法吗?

这是我重现问题的代码:

#!/usr/bin/env php7.4
<?php

if (!file_exists('myDir')) mkdir('myDir');
file_put_contents('myDir/test.txt', 'test');
chmod('myDir/test.txt', 0740);
chmod('myDir', 0750);
touch('myDir/test.txt', mktime(10, 10, 0, 1, 1, 2024));
touch('myDir', mktime(5, 42, 0, 1, 1, 2024));

if (file_exists('test.zip')) unlink('test.zip');
$zip = new ZipArchive();
if ($zip->open('test.zip', ZipArchive::CREATE) === true) {
    $zip->addEmptyDir("myDir");
    fixDirAttributes($zip, 'myDir', 'myDir'); // Directory already existe in current dir ./myDir
    $zip->addFile('myDir/test.txt', 'myDir/test.txt'); // file exist in ./myDir dir
    $zip->close();
    echo "Ok\n";
} else {
    echo "KO\n";
}

function fixDirAttributes(ZipArchive $zip, string $dirPath, string $pathInZip)
{
    $indexInZip = $zip->locateName('/' === mb_substr($pathInZip, -1) ? $pathInZip : $pathInZip . '/');
    if (false !== $indexInZip) {
        if (method_exists($zip, 'setMtimeIndex')) { // PHP >= 8.0.0, PECL zip >= 1.16.0
            $zip->setMtimeIndex($indexInZip, filemtime($dirPath));
        }
        $filePerms = fileperms($dirPath);
        if (false !== $filePerms) { // filePerms supported
            $zip->setExternalAttributesIndex($indexInZip, \ZipArchive::OPSYS_DEFAULT, $filePerms << 16);
        }
    }
}
php directory php-ziparchive filemtime
1个回答
0
投票

您可以使用不需要本机 PHP Zip 扩展的第 3 方 zip 库来完成此操作。

composer require nelexa/zip
$zip = new \PhpZip\ZipFile();
$zip->addFile('myDir/test.txt', 'myDir/test.txt');
$zip->saveAsFile('test.zip');
$zip->close();

默认情况下,该库将使用实时文件系统属性,但它会生成一个没有显式目录条目的存档:

Archive:  test.zip
 Length   Method    Size  Cmpr    Date    Time   CRC-32   Name
--------  ------  ------- ---- ---------- ----- --------  ----
       4  Stored        4   0% 2024-01-01 15:10 d87f7e0c  myDir/test.txt
--------          -------  ---                            -------
       4                4   0%                            1 file

当您解压缩存档时,您将获得该文件的正确 mtime,以及子目录的当前日期/时间。然而,这似乎不是您想要的,因此您可以告诉库使用从文件系统读取的实时属性显式添加单独的子目录条目:

$zip = new \PhpZip\ZipFile();
$zip->addSplFile(new \SplFileInfo('myDir'));
$zip->addFile('myDir/test.txt', 'myDir/test.txt');
$zip->saveAsFile('test.zip');
$zip->close();

这会生成一个具有所需 mtime 的专用子目录条目,并且从 7.4 到 8.3 的工作方式相同

Archive:  test.zip
 Length   Method    Size  Cmpr    Date    Time   CRC-32   Name
--------  ------  ------- ---- ---------- ----- --------  ----
       0  Stored        0   0% 2024-01-01 10:42 00000000  myDir/
       4  Stored        4   0% 2024-01-01 15:10 d87f7e0c  myDir/test.txt
--------          -------  ---                            -------
       4                4   0%                            2 files
© www.soinside.com 2019 - 2024. All rights reserved.