当我使用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.5.26时,文件的权限是正确的。
您可以通过在ZipArchive::addFile()
语句后添加以下代码来保留存档文件中的Unix权限:
$templateArchive->setExternalAttributesName($relativePath,
ZipArchive::OPSYS_UNIX,
fileperms($filePath) << 16);
这将使用实际文件的权限更新$filePath
处条目的外部属性。
Unix权限可以存储在每个条目的外部属性的ZIP文件中,但您必须移动16位才能将权限存储在外部属性的正确位置,这就是<< 16
应用于fileperms($filePath)
的输出的原因。
ZipArchive::setExternalAttributesName()
文档中还有一个Unix权限设置示例:https://secure.php.net/manual/en/ziparchive.setexternalattributesname.php
至于目录的权限,您需要使用ZipArchive::addEmptyDir()
添加目录(因为目录上的ZipArchive::addFile()
会导致错误),然后使用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();