CodeZip.php 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | saiadmin [ saiadmin快速开发框架 ]
  4. // +----------------------------------------------------------------------
  5. // | Author: sai <1430792918@qq.com>
  6. // +----------------------------------------------------------------------
  7. namespace plugin\saiadmin\utils\code;
  8. use plugin\saiadmin\exception\ApiException;
  9. /**
  10. * 代码构建 压缩类
  11. */
  12. class CodeZip
  13. {
  14. /**
  15. * 获取配置文件
  16. * @return string[]
  17. */
  18. private static function _getConfig(): array
  19. {
  20. return [
  21. 'template_path' => base_path().DIRECTORY_SEPARATOR.'plugin'.DIRECTORY_SEPARATOR.'saiadmin'.DIRECTORY_SEPARATOR.'utils'.DIRECTORY_SEPARATOR.'code'.DIRECTORY_SEPARATOR.'stub',
  22. 'generate_path' => runtime_path().DIRECTORY_SEPARATOR.'code_engine'.DIRECTORY_SEPARATOR.'saiadmin',
  23. ];
  24. }
  25. /**
  26. * 构造器
  27. */
  28. public function __construct()
  29. {
  30. // 读取配置文件
  31. $config = self::_getConfig();
  32. // 清理源目录
  33. if (is_dir($config['generate_path'])) {
  34. $this->recursiveDelete($config['generate_path']);
  35. }
  36. // 清理压缩文件
  37. $zipName = $config['generate_path'].'.zip';
  38. if (is_file($zipName)) {
  39. unlink($zipName);
  40. }
  41. }
  42. /**
  43. * 文件压缩
  44. */
  45. public function compress(bool $isDownload = false)
  46. {
  47. // 读取配置文件
  48. $config = self::_getConfig();
  49. $zipArc = new \ZipArchive;
  50. $zipName = $config['generate_path'].'.zip';
  51. $dirPath = $config['generate_path'];
  52. if ($zipArc->open($zipName, \ZipArchive::OVERWRITE | \ZipArchive::CREATE) !== true) {
  53. throw new ApiException('无法打开文件,或者文件创建失败');
  54. }
  55. $this->addFileToZip($dirPath, $zipArc);
  56. $zipArc->close();
  57. // 是否下载
  58. if ($isDownload) {
  59. $this->toBinary($zipName);
  60. } else {
  61. return $zipName;
  62. }
  63. }
  64. /**
  65. * 文件解压
  66. */
  67. public function deCompress(string $file, string $dirName)
  68. {
  69. if (!file_exists($file)) {
  70. return false;
  71. }
  72. // zip实例化对象
  73. $zipArc = new \ZipArchive();
  74. // 打开文件
  75. if (!$zipArc->open($file)) {
  76. return false;
  77. }
  78. // 解压文件
  79. if (!$zipArc->extractTo($dirName)) {
  80. // 关闭
  81. $zipArc->close();
  82. return false;
  83. }
  84. return $zipArc->close();
  85. }
  86. /**
  87. * 将文件加入到压缩包
  88. */
  89. public function addFileToZip($rootPath, $zip)
  90. {
  91. $files = new \RecursiveIteratorIterator(
  92. new \RecursiveDirectoryIterator($rootPath),
  93. \RecursiveIteratorIterator::LEAVES_ONLY
  94. );
  95. foreach ($files as $name => $file)
  96. {
  97. // Skip directories (they would be added automatically)
  98. if (!$file->isDir())
  99. {
  100. // Get real and relative path for current file
  101. $filePath = $file->getRealPath();
  102. $relativePath = substr($filePath, strlen($rootPath) + 1);
  103. // Add current file to archive
  104. $zip->addFile($filePath, $relativePath);
  105. }
  106. }
  107. }
  108. /**
  109. * 递归删除目录下所有文件和文件夹
  110. */
  111. public function recursiveDelete($dir)
  112. {
  113. // 打开指定目录
  114. if ($handle = @opendir($dir)) {
  115. while (($file = readdir($handle)) !== false) {
  116. if (($file == ".") || ($file == "..")) {
  117. continue;
  118. }
  119. if (is_dir($dir . '/' . $file)) {
  120. // 递归
  121. self::recursiveDelete($dir . '/' . $file);
  122. } else {
  123. unlink($dir . '/' . $file); // 删除文件
  124. }
  125. }
  126. @closedir($handle);
  127. }
  128. rmdir($dir);
  129. }
  130. /**
  131. * 下载二进制流文件
  132. */
  133. public function toBinary(string $fileName)
  134. {
  135. try {
  136. header("Cache-Control: public");
  137. header("Content-Description: File Transfer");
  138. header('Content-disposition: attachment; filename=' . basename($fileName)); //文件名
  139. header("Content-Type: application/zip"); //zip格式的
  140. header("Content-Transfer-Encoding: binary"); //告诉浏览器,这是二进制文件
  141. header('Content-Length: ' . filesize($fileName)); //告诉浏览器,文件大小
  142. if(ob_get_length() > 0) {
  143. ob_clean();
  144. }
  145. flush();
  146. @readfile($fileName);
  147. @unlink($fileName);
  148. } catch (\Throwable $th) {
  149. throw new ApiException('系统生成文件错误');
  150. }
  151. }
  152. }