通过 Internet 传输文件时压缩文件有很多优点。在大多数情况下,压缩格式的所有文件的总大小都会大幅下降。这意味着您将节省一些带宽,用户也将获得更快的下载速度。用户下载文件后,可以随时解压缩。简而言之,压缩可以让您和您的访问者更轻松地通过 Internet 提供文件。
可能会阻止您压缩文件或使过程非常烦人的一个因素是您可能手动执行此操作。幸运的是PHP 附带了许多专门处理文件压缩和提取的扩展。您可以使用这些扩展中提供的功能在 PHP 中自动压缩文件。
本教程将教您如何在 PHP 中将文件压缩和解压缩(压缩和解压缩)到 zip 归档文件中。您还将学习如何删除或重命名存档中的文件,而无需先提取它们。
在 PHP 中压缩单个文件
压缩目录中的多个文件
修改或覆盖档案
从档案中提取内容
获得对档案的更多控制权
在 PHP 中压缩单个文件
PHPZipArchive
类有很多属性和方法可以帮助您压缩和解压缩所有文件。
您可以一次将一个文件添加到您的 zip 存档中,也可以一次添加整个目录。无论哪种情况,第一步都是创建一个新ZipArchive
实例,然后调用该open($filename, [$flags])
方法。此方法将打开一个新的 zip 存档以进行读取、写入或其他修改。可选参数有五个有效值,$flag
它们确定如何处理不同的情况。
ZipArchive::OVERWRITE
— 如果指定存档中的内容已经存在,此标志将覆盖它。ZipArchive::CREATE
— 如果该标志尚不存在,则该标志将创建一个新存档。ZipArchive::EXCL
— 如果存档已存在,此标志将导致错误。ZipArchive::CHECKCONS
— 该标志将告诉 PHP 对存档执行额外的一致性检查,如果检查失败则给出错误。ZipArchive::RDONLY
— 该标志在 PHP 7.4.3 中可用,并允许您以只读模式打开存档。
您可以查看此方法的文档以了解在打开文件失败时返回的不同错误代码。如果 zip 文件打开或创建成功,该方法将返回true
.
您将不得不在不同情况下使用不同的标志组合以避免任何意外结果。例如,ZipArchive::OVERWRITE
如果您不关心现有存档的内容,请使用该标志。如果不存在具有该特定名称的存档,它将不会创建新存档。
如果不存在具有该特定名称的存档,则可以使用ZipArchive::OVERWRITE
和的组合ZipArchive::CREATE
覆盖现有存档并创建新存档。这是一个例子:
$zip ->open( 'my_compressed_files.zip' , ZipArchive::OVERWRITE|ZipArchive::CREATE); |
使用该ZipArchive::CREATE
标志时,您会注意到它开始修改现有存档(如果已存在)。这可能是您真正想要做的,但它也可能产生一些意想不到的后果。您可以使用ZipArchive::CREATE
和的组合ZipArchive::EXCL
来确保您只使用以前不存在的档案。
$zip ->open( 'new_compressed_files.zip' , ZipArchive::EXCL|ZipArchive::CREATE); |
成功打开存档后,您可以使用该addFile($filename, $localname, $start, $length)
方法将给定路径中的任何文件添加到存档中。该$filename
参数是要添加到存档的文件的路径。该$localname
参数用于为文件分配名称以将其存储在存档中。addFile()
每次想要将新文件添加到存档时,您都可以调用。
将所有必要的文件添加到存档后,您只需调用该close()
方法即可将其关闭并保存更改。
假设您有一个网站,允许用户下载不同字体的字体文件以及使用它们的许可信息。像这样的文件将是使用 PHP 自动归档的完美示例。以下代码向您展示了如何做到这一点。
<?php $zip = new ZipArchive(); $zip ->open( 'compressed/font_files.zip' , ZipArchive::CREATE); $zip ->addFile( 'fonts/Monoton/Monoton-Regular.ttf' , 'Monoton-Regular.ttf' ); $zip ->addFile( 'fonts/Monoton/OFL.txt' , 'license.txt' ); $zip ->close(); ?> |
我们首先创建一个ZipArchive
实例,然后使用该open()
方法创建我们的存档。该addFile()
方法将我们实际的.ttf字体文件和.txt许可证文件添加到存档中。
您应该注意原始文件位于fonts/Monoton目录中。但是,PHP 代码将它们直接放在我们存档的根目录中。您可以更改目录结构以及进入存档的文件的名称。
压缩目录中的多个文件
一段时间后,将单个文件添加到您的存档中可能会很累。例如,您可能希望在一个目录中创建所有.pdf或.png文件的存档。在这种情况下,该addGlob($pattern, $flags, $options)
方法将非常有用。此方法的唯一缺点是您无法控制存档中单个文件的位置。但是,您仍然可以使用该$options
参数影响存档内的目录结构。选项以关联数组的形式传递。
add_path
— 您分配的值add_path
以存档中文件的本地路径为前缀。remove_path
— 您分配的值remove_path
用于从添加到存档的不同文件的路径中删除匹配的前缀。remove_all_path
—将值设置remove_all_path
为true
将删除文件路径中除文件名之外的所有内容。在这种情况下,文件将添加到存档的根目录。
重要的是要记住,路径的删除是在add_path
.
以下代码片段将阐明addGlob()
所有这些选项的使用。
$zip = new ZipArchive(); $zip ->open( 'compressed/user_archive.zip' , ZipArchive::CREATE); $options = array ( 'add_path' => 'light_wallpapers/' , 'remove_all_path' => TRUE); $zip ->addGlob( 'lights/*.jpg' , 0, $options ); $options = array ( 'add_path' => 'font_files/' , 'remove_all_path' => TRUE); $zip ->addGlob( 'documents/*.ttf' , 0, $options ); $options = array ( 'add_path' => 'pdf_books/' , 'remove_all_path' => TRUE); $zip ->addGlob( 'documents/*.pdf' , 0, $options ); $options = array ( 'add_path' => 'images/' , 'remove_all_path' => TRUE); $zip ->addGlob( 'documents/*.{jpg, png}' , GLOB_BRACE, $options ); $zip ->close(); |
像往常一样,我们首先创建一个ZipArchive
实例,然后使用该open()
方法创建我们的存档。每次调用方法之前,我们还为数组中的add_path
键指定不同的值。这样,我们可以一次处理一组特定的文件,并相应地提供归档选项。$options
addGlob()
在第一种情况下,我们遍历lights目录中的所有.jpg文件,并将它们放置在归档文件的light_wallpapers目录中。同样,我们遍历文档目录中的所有.ttf文件,然后将它们放入存档中名为font_files的文件夹中。最后,我们一次遍历文档中的所有.jpg和.png文件,并将它们全部放在images目录中。
如您所见,$options
参数中的值对于组织存档内的内容很有用。
修改或覆盖档案
您可以组合不同的标志和选项以在存档中实现特定的文件和目录结构。正如我前面提到的,我们可以使用该open()
方法打开一个新的或现有的存档进行读写。
open()
在本节中,我们将了解由于传递给方法和$options
传递给方法的标志的不同组合而可能出现的差异addGlob()
。假设没有名为compressed_files.zip的存档,我们运行以下代码。
<?php $zip = new ZipArchive(); $zip ->open( 'compressed_files.zip' , ZipArchive::CREATE); $options = array ( 'add_path' => 'wallpapers/' ); $zip ->addGlob( 'files/images/*.*' , 0, $options ); $zip ->close(); ?> |
它将从目录files/images中获取所有图像文件,并将它们放在存档根目录的壁纸目录中。存档中图像文件的路径是wallpapers/files/images。
您可以使用以下一组选项摆脱所有图像的初始路径:
$options = array ( 'add_path' => 'wallpapers/' , 'remove_all_path' => TRUE); |
图像文件现在将直接存储在壁纸中,原始图像路径将被丢弃。
正如我之前提到的,ZipArchive::CREATE
将创建一个新存档或开始修改现有存档(如果它已经存在)。您不会收到有关正在修改现有存档的任何警告。这意味着如果您执行本节中的代码以创建存档,然后在将原始选项替换为新选项后再次执行,您将得到一些意想不到的结果。
然后存档将包含一个壁纸目录,其中包含子目录文件/图像以及直接在壁纸目录中的图像。刚开始时可能会有些混乱,这可能会让您想知道为什么$options
您设置的内容没有受到尊重。
ZipArchive::CREATE|ZipArchive::OVERWRITE
如果要覆盖存档中的所有内容(如果它已经存在,但不希望代码在不存在时抛出错误),请务必确保使用它。
另请记住,自 libzip 1.6.0 以来,空文件不再被视为有效存档。
从档案中提取内容
该类ZipArchive
有一个方法被调用extractTo($destination, $entries)
来提取档案的内容。您可以使用它来提取存档中的所有内容或仅提取一些特定文件。该$entries
参数可用于指定要提取的单个文件名,也可以使用它来传递文件数组。
要记住的重要一点是,您需要在存档中指定文件的正确路径才能提取它。例如,我们在上一节中归档了一个名为AlegreyaSans-Light.ttf的字体文件。该文件存储在存档中名为font_files的目录中。这意味着您需要在$entries
参数中指定的路径是font_files/AlegreyaSans-Light.ttf而不仅仅是AlegreyaSans-Light.ttf。
提取过程中会保留目录和文件结构,并将文件提取到各自的目录中。
<?php $zip = new ZipArchive(); $zip ->open( 'compressed/user_archive.zip' , ZipArchive::CREATE); $zip ->extractTo( 'uncompressed/' , 'font_files/AlegreyaSans-Light.ttf' ); $zip ->close(); ?> |
如果省略第二个参数,该方法将提取存档中的所有文件。
获得对档案的更多控制权
该类ZipArchive
还具有许多其他方法和属性,可帮助您在提取其所有内容之前获取有关存档的更多信息。
count()
您可以使用该方法计算存档中的文件数。另一种选择是使用该numFiles
属性。它们可用于遍历存档中的所有文件并仅提取您需要的文件 - 或者您可以对它们执行其他操作,例如从存档中删除它们。
在以下示例中,我们将删除存档中包含单词Italic的所有文件。类似的代码可用于删除所有不包含特定单词的文件。您还可以遍历这些文件并将特定单词替换为其他单词。
<?php $zip = new ZipArchive(); $zip ->open( 'compressed/user_archive.zip' , ZipArchive::CREATE); $file_count = $zip -> count (); for ( $i = 0; $i < $file_count ; $i ++) { $file_name = $zip ->getNameIndex( $i ); if ( stripos ( $file_name , 'Italic' ) !== false) { $zip ->deleteName( $file_name ); } } $zip ->close(); ?> |
在上面的代码中,我们deleteName()
用于删除单个文件。但是,您也可以使用它来删除整个目录。
类似的功能renameName($oldname, $newname)
可用于更改存档中任何文件的名称。$newname
如果标题为的文件已存在,您将收到错误消息。
最后的想法
我们已经介绍了ZipArchive
该类的许多非常有用的方法,它们将使 PHP 中文件的自动压缩和提取变得轻而易举。您现在应该能够根据自己的标准一次压缩单个文件或一组文件。同样,您应该能够从存档中提取任何特定文件而不会影响其他内容。
在 和 的帮助下count()
,numFiles
您将获得对单个文件的更多控制权,重命名或删除它们将非常容易。您应该至少阅读一次文档以了解更多此类功能。
发表评论