Finally it’s time for PHP’s specialty. We have learned about Bzip2, LZF, Phar and rar compression before. Related extensions are used in PHP, but they are either too unpopular, or many functions are not supported. Zip is a popular compression format with the greatest functional support in PHP, or it is a common compression format. Of course, this is mainly due to the fact that Zip is also the de facto universal compression format in the Linux environment.
Installation
For PHP, the Zip extension has been integrated into the PHP installation package. You can directly add --with-zip when Configure, if not during installation. With this parameter, we can also find the source code under ext/zip of the source code package, and then install it through extended installation.
Create a compressed package
$zip = new ZipArchive(); $filename = './test_zip.zip'; if($zip->open($filename, ZIPARCHIVE::CREATE)!==TRUE){ exit('cannot open ' . $filename .'\n'); } // 加入文字类型的文件 $zip->addFromString('testfile1.txt' . time(), "#1"); $zip->addFromString('testfile2.txt' . time(), "#2"); // 加入已存在的文件 $zip->addFile('rar.php', 'newrar.php'); echo $zip->numFiles, PHP_EOL; // 文件数量 echo $zip->status, PHP_EOL; // 压缩包状态 $zip->close(); // 使用操作系统的 unzip 查看 // # unzip -l test_zip.zip // Archive: test_zip.zip // Length Date Time Name // --------- ---------- ----- ---- // 2 07-08-2020 08:57 testfile1.txt1594169845 // 2 07-08-2020 08:57 testfile2.txt1594169845 // 2178 07-07-2020 08:55 newrar2.php // --------- ------- // 2182 3 files
The rar extension that we have learned before cannot package files or create new compressed packages, but what we learned as soon as Zip came up is to create a new compressed package. . After instantiating a ZipArchive object, we can use the open() function to open or create a compressed archive file. Next, we used two methods of adding content. addFromString() is to add a text type file, that is, convert a piece of text into a text file and save it in this compressed package. In addition, we use addFile() to add external files to this compressed package.
[Recommended learning: PHP video tutorial]
numFiles and status attributes can respectively view the number of files in the compressed package file and the current compressed package status information. Finally, just use close() to close the handle. In this way, a simple Zip archive file is created. We can directly use the unzip command of the operating system to view the contents of the compressed package.
Read the contents and information of the compressed package
$zip = new ZipArchive(); $zip->open('./test_zip.zip'); print_r($zip); // 压缩包信息 // ZipArchive Object // ( // [status] => 0 // [statusSys] => 0 // [numFiles] => 40 // [filename] => /data/www/blog/test_zip.zip // [comment] => // ) var_dump($zip); // object(ZipArchive)#2 (5) { // ["status"]=> // int(0) // ["statusSys"]=> // int(0) // ["numFiles"]=> // int(40) // ["filename"]=> // string(27) "/data/www/blog/test_zip.zip" // ["comment"]=> // string(0) "" // } echo $zip->numFiles, PHP_EOL; echo $zip->status, PHP_EOL; echo $zip->statusSys, PHP_EOL; echo $zip->filename, PHP_EOL; echo $zip->comment, PHP_EOL; echo $zip->count(), PHP_EOL; for ($i=0; $i<$zip->numFiles;$i++) { echo "index: $i\n"; // 打印每个文件实体信息 print_r($zip->statIndex($i)); // index: 0 // Array // ( // [name] => testfile1.txt1594169845 // [index] => 0 // [crc] => 2930664868 // [size] => 2 // [mtime] => 1594169844 // [comp_size] => 2 // [comp_method] => 0 // [encryption_method] => 0 // ) // …… $entry = $zip->statIndex($i); if($entry['name'] == 'newrar.php'){ // 仅解压 newrar.php 文件到指定目录 $zip->extractTo('./test_zip_single', $entry['name']); } } // 修改压缩包内的文件名 $zip->renameName('newrar.php', 'newrar2.php'); print_r($zip->getFromIndex(2)); // 获取第二个文件的内容 print_r($zip->getFromName('newrar2.php')); // 获取指定文件名的文件内容 $zip->extractTo('./test_zip'); // 解压整个压缩包到指定目录 $zip->close();
In fact, reading is the same step, instantiate a ZipArchive class, and then open() to open a compressed package file handle. Then you can directly output some attribute information of the compressed package. We can loop through and get information about each file entity through the statIndex() method. It should be noted here that statIndex() obtains file information, not the content of the file.
Of course, we can also directly obtain the specified file through getFromIndex() or getFromName(). Use renameName() to directly rename the files inside the compressed package, and use extractTo() to extract the specified file or the entire compressed package to the specified directory. If the second parameter of the extractTo() method specifies content, only the specified file will be decompressed.
Compress directory, setting instructions and reading files in stream and pseudo-protocol methods
Since it is a compression package tool, the most commonly used one is to directly package multiple files or directories. At the same time, there are also many compressed packages where you can set some instructions, passwords, etc. In addition, we can also directly obtain the contents of a file in the compressed package through the exclusive zip:// pseudo-protocol. These functions can be used very easily and conveniently in the PHP Zip extension.
Compressed directory
// 压缩目录 $zip = new ZipArchive(); $zip->open('./test_zip2.zip', ZIPARCHIVE::CREATE); $zip->addFile('rar.php', 'newrar.php'); $zip->addGlob('./test_zip/*.{php,txt}', GLOB_BRACE, ['add_path'=> 'new_path/']);
Using addGlob directly can help us package the contents of all files in a certain file directory. At the same time, its third parameter can also specify the path address of these files inside the compressed package.
Setting instructions and password
// 设置注释、密码 $zip->setArchiveComment('This is rar Comment!'); $zip->setPassword('123'); $zip->close(); // 使用操作系统 unzip 查看 // # unzip -l test_zip2.zip // Archive: test_zip2.zip // This is rar Comment! // Length Date Time Name // --------- ---------- ----- ---- // 2178 07-07-2020 08:55 newrar.php // 2178 07-08-2020 10:36 new_path/./test_zip/newrar.php // 2178 07-08-2020 10:36 new_path/./test_zip/newrar2.php // --------- ------- // 6534 3 files
The instructions, comments and password for setting the compressed package are all ready-made function methods that can be used directly. We can use the unzip command of the operating system again to view the annotation information of the compressed package and the contents of the packaged directory. The contents of the test_zip/ directory originally tested were placed in the new_path/ directory, which is the path address inside the compressed package we customized.
Read files using streams and pseudo-protocols
// 流、伪协议方法读取压缩包内容 $zip = new ZipArchive(); $zip->open('./test_zip2.zip'); // 获取文件流 $fp = $zip->getStream('newrar.php'); while(!feof($fp)){ echo fread($fp, 2); } fclose($fp); // 使用伪协议 $fp = fopen('zip://' . dirname(__FILE__) . '/test_zip2.zip#newrar.php', 'r'); while(!feof($fp)){ echo fread($fp, 2); } fclose($fp); // file_get_contents 使用伪协议 echo file_get_contents('zip://' . dirname(__FILE__) . '/test_zip2.zip#newrar.php'); // 直接使用伪协议将文件拷贝出来 copy('zip://' . dirname(__FILE__) . '/test_zip2.zip#newrar.php', './newrar2.php');
First, we directly obtain the stream of a file in the compressed package through the getStream() method. This method is used by almost all compression extensions. Provides a way to read files. The following method uses the zip:// pseudo-protocol to directly use the fopen() and file_get_contents() functions to read a file inside the compressed package. Now that we have such a convenient pseudo-protocol, it becomes very easy for us to simply obtain and decompress a file. We can just use the copy() function to copy the file.
总结
是不是感觉比 rar 的操作强大了许多。都说了这是 PHP 主力支持的一种通用压缩格式,所以当然功能会丰富许多,而且还有很多的函数方法我们并没有全部列出来,如果全列出来的话还不如大家自己去看手册呢。这里就是以一些简单的例子让大家看到这类扩展功能的操作,方便大家在业务选型的时候能够快速的联想到我们 PHP 就已经提供了这些现成的扩展。需要了解 Zip 其它内容的同学可以移步最下方的链接直接进入手册中查阅。
测试代码: https://github.com/zhangyue0503/dev-blog/blob/master/php/202007/source/PHP%E7%9A%84zip%E5%8E%8B%E7%BC%A9%E5%B7%A5%E5%85%B7%E6%89%A9%E5%B1%95%E5%8C%85%E5%AD%A6%E4%B9%A0.php 参考文档:https://www.php.net/manual/zh/book.zip.php