ExportZip.php 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. <?php
  2. namespace App\Console\Commands;
  3. use Illuminate\Console\Command;
  4. use Illuminate\Support\Facades\Storage;
  5. use Illuminate\Support\Facades\Log;
  6. use App\Tools\RedisClusters;
  7. use Illuminate\Support\Facades\App;
  8. use Symfony\Component\Process\Process;
  9. use Symfony\Component\Process\Exception\ProcessFailedException;
  10. class ExportZip extends Command
  11. {
  12. /**
  13. * The name and signature of the console command.
  14. *
  15. * @var string
  16. */
  17. protected $signature = 'export:zip {filename : filename} {title : title} {format? : zip file format 7z,lzma,gz }';
  18. /**
  19. * The console command description.
  20. *
  21. * @var string
  22. */
  23. protected $description = '压缩导出的文件';
  24. /**
  25. * Create a new command instance.
  26. *
  27. * @return void
  28. */
  29. public function __construct()
  30. {
  31. parent::__construct();
  32. }
  33. /**
  34. * Execute the console command.
  35. *
  36. * @return int
  37. */
  38. public function handle()
  39. {
  40. Log::debug('export offline: 开始压缩');
  41. $this->info('export offline: 开始压缩');
  42. $exportPath = 'app/public/export/offline';
  43. $exportFile = $this->argument('filename');
  44. Log::debug('export offline: zip file {filename} {format}',
  45. [
  46. 'filename'=>$exportFile,
  47. 'format'=>$this->argument('format')
  48. ]);
  49. switch ($this->argument('format')) {
  50. case '7z':
  51. $zipFile = $exportFile . ".7z";
  52. break;
  53. case 'lzma':
  54. $zipFile = $exportFile . ".lzma";
  55. break;
  56. default:
  57. $zipFile = $exportFile . ".gz";
  58. break;
  59. }
  60. //
  61. $exportFullFileName = storage_path($exportPath.'/'.$exportFile);
  62. if(!file_exists($exportFullFileName)){
  63. Log::error('export offline: no db file {filename}',['filename'=>$exportFullFileName]);
  64. $this->error('export offline: no db file {filename}'.$exportFullFileName);
  65. return 1;
  66. }
  67. $zipFullFileName = storage_path($exportPath.'/'.$zipFile);
  68. if(file_exists($zipFullFileName)){
  69. Log::debug('export offline: delete old zip file:'.$zipFullFileName);
  70. unlink($zipFullFileName);
  71. }
  72. shell_exec("cd ".storage_path($exportPath));
  73. switch ($this->argument('format')) {
  74. case '7z':
  75. $command = [
  76. '7z', 'a', '-t7z', '-m0=lzma',
  77. '-mx=9', '-mfb=64', '-md=32m', '-ms=on',
  78. $zipFullFileName,$exportFullFileName
  79. ];
  80. break;
  81. case 'lzma':
  82. $command = ['xz', '-k', '-9', '--format=lzma',$exportFullFileName];
  83. break;
  84. default:
  85. $command = ['gzip', $exportFullFileName];
  86. break;
  87. }
  88. $this->info( implode(' ',$command));
  89. Log::debug('export offline zip start',['command'=>$command,'format'=>$this->argument('format')]);
  90. $process = new Process($command);
  91. $process->run();
  92. $this->info($process->getOutput());
  93. $this->info('压缩完成');
  94. Log::debug('zip file {filename} in {format} saved.',
  95. [
  96. 'filename'=>$exportFile,
  97. 'format'=>$this->argument('format')
  98. ]);
  99. $url = array();
  100. foreach (config('mint.server.cdn_urls') as $key => $cdn) {
  101. $url[] = [
  102. 'link' => $cdn . '/' . $zipFile,
  103. 'hostname' =>'china cdn-' . $key,
  104. ];
  105. }
  106. $bucket = config('mint.attachments.bucket_name.temporary');
  107. $tmpFile = $bucket.'/'. $zipFile ;
  108. $this->info('upload file='.$tmpFile);
  109. Log::debug('export offline: upload file {filename}',['filename'=>$tmpFile]);
  110. Storage::put($tmpFile, file_get_contents($zipFullFileName));
  111. $this->info('upload done file='.$tmpFile);
  112. Log::debug('export offline: upload done {filename}',['filename'=>$tmpFile]);
  113. if (App::environment('local')) {
  114. $link = Storage::url($tmpFile);
  115. }else{
  116. try{
  117. $link = Storage::temporaryUrl($tmpFile, now()->addDays(2));
  118. }catch(\Exception $e){
  119. $this->error('generate temporaryUrl fail');
  120. Log::error('export offline: generate temporaryUrl fail {Exception}',
  121. [
  122. 'exception'=>$e,
  123. 'file'=>$tmpFile
  124. ]);
  125. return 1;
  126. }
  127. }
  128. $this->info('link = '.$link);
  129. Log::info('export offline: link='.$link);
  130. $url[] = [
  131. 'link'=>$link,
  132. 'hostname'=>'Amazon cloud storage(Hongkong)',
  133. ];
  134. $info = RedisClusters::get('/offline/index');
  135. if(!is_array($info)){
  136. $info = array();
  137. }
  138. $info[] = [
  139. 'title' => $this->argument('title'),
  140. 'filename'=>$zipFile,
  141. 'url' => $url,
  142. 'create_at'=>date("Y-m-d H:i:s"),
  143. 'chapter'=>RedisClusters::get("/export/chapter/count"),
  144. 'filesize'=>filesize($zipFullFileName),
  145. 'min_app_ver'=>'1.3',
  146. ];
  147. RedisClusters::put('/offline/index',$info);
  148. sleep(5);
  149. try {
  150. unlink($exportFullFileName);
  151. } catch (\Throwable $th) {
  152. Log::error('export offline: delete file fail {Exception}',
  153. [
  154. 'exception'=>$th,
  155. 'file'=>$exportFullFileName
  156. ]);
  157. }
  158. return 0;
  159. }
  160. }