使用PHP ZipArchive创建Zip文件时如何保留符号链接?
PHP ZipArchive 保留符号链接的解决方案
默认使用ZipArchive::addFile()会将符号链接解析为实际文件并复制内容,若要保留符号链接本身以减小归档体积,可通过以下方式实现:
核心思路
遍历文件时,先判断当前条目是否为符号链接:
- 若是符号链接:创建空条目,再通过
setExternalAttributesName()标记其为符号链接类型,并设置链接指向的目标 - 若为普通文件:仍使用原
addFile()方法添加
完整代码示例
$zip = new ZipArchive(); if ($zip->open($zipFile, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== true) { // 处理打开失败的情况 exit('无法创建或打开归档文件'); } foreach($filesToZip as $name => $file) { $filePath = $file->getPathname(); $relativePath = substr($filePath, strlen($rootPath) + 1); if ($file->isLink()) { // 获取符号链接指向的目标路径 $linkTarget = readlink($filePath); // 添加空的归档条目 $zip->addEmptyFile($relativePath); // 获取原符号链接的权限 $perms = fileperms($filePath) & 0777; // 设置外部属性:权限 + 符号链接文件类型(0120000为S_IFLNK的八进制值) $externalAttr = ($perms << 16) | 0120000; // 标记条目为符号链接并设置目标 $zip->setExternalAttributesName( $relativePath, ZipArchive::OPSYS_UNIX, $externalAttr, $linkTarget ); } elseif (!$file->isDir()) { // 处理普通文件 $zip->addFile($filePath, $relativePath); } } $zip->close();
注意事项
- 该方案要求PHP 7.2及以上版本,因为
ZipArchive::setExternalAttributesName()的$link参数(用于指定符号链接目标)在7.2版本才被引入 - 避免使用
getRealPath(),该方法会解析符号链接到真实文件路径,导致归档中添加的是实际文件而非链接
内容的提问来源于stack exchange,提问作者G. Kolev
相关产品推荐
相关产品推荐

