当前位置:   article > 正文

PHP操作ZIP之ZipArchive类以及如何避免生成压缩文件带有目录层级的问题_php ziparchive压缩目录

php ziparchive压缩目录

常用的方法

php ZipArchive可以说是php自带的一个函数了,他可对对文件进行压缩与解压缩处理,但是使用此类之前我们必须在php.ini中把extension=php_zip.dll前面的分号有没有去掉,然后再重启Apache这样才能使用这个类库。

ziparchive 可选参数,更多的使用例子,参考PHP - Manual: ZipArchive - 互联网笔记

ZipArchive::addEmptyDir

添加一个新的文件目录

  1. <?php
  2. $zip = new ZipArchive;
  3. if ($zip->open('test.zip') === TRUE) {
  4. if($zip->addEmptyDir('newDirectory')) {
  5. echo 'Created a new root directory';
  6. } else {
  7. echo 'Could not create the directory';
  8. }
  9. $zip->close();
  10. } else {
  11. echo 'failed';
  12. }
  13. ?>

ZipArchive::addFile

将文件添加到指定zip压缩包中。

ZipArchive::addFromString

添加的文件同时将内容添加进去

ZipArchive::close

关闭ziparchive

ZipArchive::extractTo

将压缩包解压

ZipArchive::open

打开一个zip压缩包

ZipArchive::getStatusString

返回压缩时的状态内容,包括错误信息,压缩信息等等

ZipArchive::deleteIndex

删除压缩包中的某一个文件,如:deleteIndex(0)删除第一个文件

ZipArchive::deleteName

删除压缩包中的某一个文件名称,同时也将文件删除。

ZipArchive::open

  1. <?php
  2. $zip = new ZipArchive;
  3. $res = $zip->open('test.zip', ZipArchive::CREATE);
  4. if ($res === TRUE) {
  5. $zip->addFromString('test.txt', 'file content goes here');
  6. $zip->addFile('data.txt', 'entryname.txt');
  7. $zip->close();
  8. echo 'ok';
  9. } else {
  10. echo 'failed';
  11. }
  12. ?>

  1. <?php
  2. $name = tempnam(sys_get_temp_dir(), "FOO");
  3. $zip = new ZipArchive;
  4. $res = $zip->open($name, ZipArchive::OVERWRITE); /* truncate as empty file is not valid */
  5. if ($res === TRUE) {
  6. $zip->addFile('data.txt', 'entryname.txt');
  7. $zip->close();
  8. echo 'ok';
  9. } else {
  10. echo 'failed';
  11. }
  12. ?>

基本使用例

解压缩zip文件

注意,解压的文件夹中不要有中文!会引起乱码!

  1. $zip = new ZipArchive;//新建一个ZipArchive的对象
  2. /*
  3. 通过ZipArchive的对象处理zip文件
  4. $zip->open这个方法的参数表示处理的zip文件名。
  5. 如果对zip文件对象操作成功,$zip->open这个方法会返回TRUE
  6. */
  7. if ($zip->open('test.zip'))
  8. {
  9. $zip->extractTo('images');//假设解压缩到在当前路径下images文件夹的子文件夹php
  10. $zip->close();//关闭处理的zip文件
  11. }

文件追加内容添加到zip文件

  1. zip = new ZipArchive;
  2. $res = $zip->open('test.zip', ZipArchive::CREATE);
  3. if ($res) {
  4. $zip->addFromString('test.txt', 'file content goes here');
  5. $zip->close();
  6. echo 'ok';
  7. } else {
  8. echo 'failed';
  9. }

建议:$zip->open 使用try-catch去捕捉

  1. try {
  2. $zipResult = $zip->open($zipPath, ZipArchive::CREATE | ZipArchive::OVERWRITE);
  3. //关闭处理的zip文件
  4. $zip->close();
  5. } catch (Exception $e) {
  6. exit( $e->getMessage());
  7. }

将服务器上的文件夹打包成zip文件

  1. function addFileToZip($path, $zip) {
  2. $handler = opendir($path); //打开当前文件夹由$path指定。
  3. /*
  4. 循环的读取文件夹下的所有文件和文件夹
  5. 其中$filename = readdir($handler)是每次循环的时候将读取的文件名赋值给$filename,
  6. 为了不陷于死循环,所以还要让$filename !== false。
  7. 一定要用!==,因为如果某个文件名如果叫'0',或者某些被系统认为是代表false,用!=就会停止循环
  8. */
  9. while (($filename = readdir($handler)) !== false) {
  10. //文件夹文件名字为'.'和‘..’,不要对他们进行操作
  11. if ($filename != "." && $filename != "..") {
  12. $filePath = "{$path}/{$filename}";
  13. // 如果读取的某个对象是文件夹,则递归
  14. if (is_dir($filePath)) {
  15. addFileToZip($filePath, $zip);
  16. } else {
  17. var_dump($filePath);
  18. // 将文件加入zip对象 传入第二个参数是避免出现目录层级的问题
  19. $zip->addFile($filePath, pathinfo($filePath, PATHINFO_BASENAME));
  20. }
  21. }
  22. }
  23. @closedir($path);
  24. }
  25. $STATICS_PATH = 'd:/xampp/htdocs/xin-card';
  26. $templatePath = '2023/03/0d9cf19188485dc70e21a1aae4ffad8d';
  27. // 要下载文件的最终目录
  28. $finalPath = "{$STATICS_PATH}/templates/{$templatePath}";
  29. if(!file_exists($finalPath)) {
  30. exit('路径不存在');
  31. }
  32. $zip = new ZipArchive();
  33. $zipName = time() . '.zip';
  34. // d:/xampp/htdocs/xin-card/zip/187823213.zip
  35. $zipPath = "{$STATICS_PATH}/zip/{$zipName}";
  36. try {
  37. $zipResult = $zip->open($zipPath, ZipArchive::CREATE | ZipArchive::OVERWRITE);
  38. //调用方法,对要打包的根目录进行操作,并将ZipArchive的对象传递给方法
  39. addFileToZip($finalPath, $zip);
  40. //关闭处理的zip文件
  41. $zip->close();
  42. } catch (Exception $e) {
  43. exit( $e->getMessage());
  44. }

解决生成压缩文件带有目录层级的问题

比如上面的addFileToZip方法,我一开始是这么写的:

  1. if (is_dir($filePath)) {
  2. addFileToZip($filePath, $zip);
  3. } else {
  4. $zip->addFile($filePath);
  5. }

这样写最终导致的后果就是生成的压缩文件,里面带有目录层级!

像这样:D:\xampp\htdocs\xin-card\statics\templates-packages\1679986315\D_\xampp\htdocs\xin-card\statics\templates-packages\2023\03\0d9cf19188485dc70e21a1aae4ffad8d 

实际上只有最后的文件夹才是我想要的!

如果你使用php ZipArchive  addFile 方法把多个文件压缩在1个目录时会产生一个问题,我们只想要在当前目录把所有文件放在一起,结果他安装每个文件的所在目录在当前目录创建一遍,解决方式如下:

  1. $allAttachment = [
  2. '1.png',
  3. '2.png',
  4. '3.png',
  5. '4.png',
  6. ];
  7. // 循环保存文件到Zip中
  8. foreach ($allAttachment as $attachmentItem) {
  9. $rootpath = 'd:/xampp/htdocs/xin-cards/';
  10. if ($attachmentItem) {
  11. $attachmentItem = "$rootpath/$attachmentItem";
  12. // 添加文件
  13. $zip->addFile($attachmentItem);
  14. // 对添加的文件重新命名,避免出现目录问题
  15. $zip->renameName($attachmentItem, basename($attachmentItem));
  16. }
  17. }
  18. // 关闭
  19. $zip->close();
  20. 如果不能解决您的问题,可以尝试如下方式
  21. // 添加文件
  22. $zip->addFile($attachmentItem, pathinfo($attachmentItem, PATHINFO_BASENAME));

浏览器下载并删除压缩文件

以下是打包服务器上某个文件夹中所有文件,并下载的然后再删除压缩文件的全部代码:

  1. <?php
  2. $STATICS_PATH = PATH['statics'];
  3. $templatePath = '2023/03/0d9cf19188485dc70e21a1aae4ffad8d';
  4. $finalPath = "{$STATICS_PATH}/templates-packages/{$templatePath}";
  5. if(!file_exists($finalPath)) {
  6. exit('路径不存在');
  7. }
  8. function addFileToZip($path, $zip) {
  9. $handler = opendir($path); //打开当前文件夹由$path指定。
  10. /*
  11. 循环的读取文件夹下的所有文件和文件夹
  12. 其中$filename = readdir($handler)是每次循环的时候将读取的文件名赋值给$filename,
  13. 为了不陷于死循环,所以还要让$filename !== false。
  14. 一定要用!==,因为如果某个文件名如果叫'0',或者某些被系统认为是代表false,用!=就会停止循环
  15. */
  16. while (($filename = readdir($handler)) !== false) {
  17. //文件夹文件名字为'.'和‘..’,不要对他们进行操作
  18. if ($filename != "." && $filename != "..") {
  19. $filePath = "{$path}/{$filename}";
  20. // 如果读取的某个对象是文件夹,则递归
  21. if (is_dir($filePath)) {
  22. addFileToZip($filePath, $zip);
  23. } else {
  24. // 将文件加入zip对象 传入第二个参数是避免出现目录层级的问题
  25. $zip->addFile($filePath, pathinfo($filePath, PATHINFO_BASENAME));
  26. }
  27. }
  28. }
  29. @closedir($path);
  30. }
  31. $zip = new ZipArchive();
  32. $zipName = time() . '.zip';
  33. $zipPath = "{$STATICS_PATH}/templates-packages/{$zipName}";
  34. try {
  35. $zipResult = $zip->open($zipPath, ZipArchive::CREATE | ZipArchive::OVERWRITE);
  36. //调用方法,对要打包的根目录进行操作,并将ZipArchive的对象传递给方法
  37. addFileToZip($finalPath, $zip);
  38. //关闭处理的zip文件
  39. $zip->close();
  40. //下载文件
  41. $file = fopen($zipPath, "r");
  42. //返回的文件类型
  43. Header("Content-type: application/octet-stream");
  44. //按照字节大小返回
  45. Header("Accept-Ranges: bytes");
  46. //返回文件的大小
  47. Header("Accept-Length: " . filesize($zipPath));
  48. //这里设置客户端的弹出对话框显示的文件名
  49. Header("Content-Disposition: attachment; filename=" . $zipName);
  50. //一次性将数据传输给客户端
  51. //echo fread($file, filesize($filePath));
  52. //一次只传输1024个字节的数据给客户端
  53. //向客户端回送数据
  54. $buffer = 1024;//
  55. //判断文件是否读完
  56. while (!feof($file)) {
  57. //将文件读入内存
  58. $file_data = fread($file, $buffer);
  59. //每次向客户端回送1024个字节的数据
  60. echo $file_data;
  61. }
  62. //将生成的zip文件在服务器端删除,只需要客户端下载就行了
  63. @unlink($zipPath);
  64. } catch (Exception $e) {
  65. exit( $e->getMessage());
  66. }

相关资料

解决phpZipArchive生成压缩文件带有目录层级的问题【阿里开发者社区】

解决phpZipArchive生成压缩文件带有目录层级的问题

php开启ziparchivephpZipArchive类使用实例详解

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/338457
推荐阅读
相关标签
  

闽ICP备14008679号