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 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