ExportDownload.php 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. <?php
  2. namespace App\Tools;
  3. use Illuminate\Support\Str;
  4. use Illuminate\Support\Facades\Log;
  5. use Illuminate\Support\Facades\Storage;
  6. use Illuminate\Support\Facades\App;
  7. use App\Tools\RedisClusters;
  8. use App\Tools\Export;
  9. class ExportDownload
  10. {
  11. protected $statusKey = 'export/status';
  12. protected $statusExpiry = 3600;
  13. protected $currStatusKey = '';
  14. protected $queryId = 'id';
  15. protected $realFilename = 'index';//压缩包里的文件名
  16. protected $zipFilename = 'file.zip';
  17. protected $downloadUrl = null;
  18. protected $format = 'tex';
  19. protected $debug = false;
  20. protected $logs = [];
  21. /**
  22. * Create a new command instance.
  23. *
  24. * @return void
  25. */
  26. public function __construct($options=[])
  27. {
  28. if(isset($options['format'])){
  29. $this->format = $options['format'];
  30. }
  31. if(isset($options['debug'])){
  32. $this->debug = $options['debug'];
  33. }
  34. if(isset($options['filename'])){
  35. $this->realFilename = $options['filename'];
  36. }
  37. $this->queryId = $options['queryId'];
  38. $this->zipFilename = $this->queryId.'.zip';
  39. $this->currStatusKey = $this->statusKey . '/' . $this->queryId;
  40. }
  41. /**
  42. * progress: 0-1, error -1
  43. * message: string
  44. */
  45. public function setStatus($progress,$message=''){
  46. $this->logs[] = $message;
  47. $data = [
  48. 'progress'=>$progress,
  49. 'message'=>$message,
  50. 'log'=>$this->logs,
  51. 'content-type'=>'application/zip',
  52. ];
  53. if($this->downloadUrl){
  54. $data['url'] = $this->downloadUrl;
  55. }
  56. RedisClusters::put($this->currStatusKey,
  57. $data,
  58. $this->statusExpiry);
  59. $percent = (int)($progress * 100);
  60. return "[{$percent}%]".$message;
  61. }
  62. public function getStatus(){
  63. return RedisClusters::get($this->currStatusKey);
  64. }
  65. public function upload(string $type,$sections,$bookMeta){
  66. $outputFilename = Str::uuid();
  67. $m = new \Mustache_Engine(array('entity_flags'=>ENT_QUOTES,
  68. 'delimiters' => '[[ ]]',
  69. 'escape'=>function ($value){
  70. return $value;
  71. }));
  72. $tex = array();
  73. $tplFile = resource_path("mustache/".$type.'/'.$this->format."/main.".$this->format);
  74. $tpl = file_get_contents($tplFile);
  75. $texContent = $m->render($tpl,$bookMeta);
  76. $tex[] = [
  77. 'name' => 'main.'.$this->format,
  78. 'content' => $texContent
  79. ];
  80. foreach ($sections as $key => $section) {
  81. $tplFile = resource_path("mustache/".$type.'/'.$this->format."/section.".$this->format);
  82. $tpl = file_get_contents($tplFile);
  83. $texContent = $m->render($tpl,$section['body']);
  84. $tex[] = [
  85. 'name'=>$section['name'],
  86. 'content'=>$texContent
  87. ];
  88. }
  89. Log::debug('footnote start');
  90. //footnote
  91. $tplFile = resource_path("mustache/".$this->format."/footnote.".$this->format);
  92. if(isset($GLOBALS['note']) &&
  93. is_array($GLOBALS['note']) &&
  94. count($GLOBALS['note'])>0 &&
  95. file_exists($tplFile)){
  96. $tpl = file_get_contents($tplFile);
  97. $texContent = $m->render($tpl,['footnote'=>$GLOBALS['note']]);
  98. $tex[] = [
  99. 'name'=>'footnote.'.$this->format,
  100. 'content'=>$texContent
  101. ];
  102. }
  103. Log::debug('footnote finished');
  104. $this->setStatus(0.95,'export content done. tex count='.count($tex));
  105. Log::debug('export content done.',['tex_count'=>count($tex)]);
  106. //upload
  107. $fileDate = '';
  108. switch ($this->format) {
  109. case 'tex':
  110. $data = Export::ToPdf($tex);
  111. if($data['ok']){
  112. $this->info($data['content-type']);
  113. $fileDate = $data['data'];
  114. }else{
  115. $this->error($data['code'].'-'.$data['message']);
  116. }
  117. break;
  118. case 'html':
  119. $file = array();
  120. foreach ($tex as $key => $section) {
  121. $file[] = $section['content'];
  122. }
  123. $fileDate = implode('',$file);
  124. break;
  125. }
  126. if($this->debug){
  127. $dir = "export/{$type}/".$this->format."/".$this->zipFilename."/";
  128. $filename = $dir.$outputFilename.'.html';
  129. Log::debug('save',['filename'=>$filename]);
  130. Storage::disk('local')->put($filename, $fileDate);
  131. }
  132. $zipDir = storage_path('app/export/zip');
  133. if(!is_dir($zipDir)){
  134. $res = mkdir($zipDir,0755,true);
  135. if(!$res){
  136. Log::error('mkdir fail path='.$zipDir);
  137. return 1;
  138. }
  139. }
  140. $zipFile = $zipDir.'/'. $outputFilename .'.zip';
  141. Log::debug('export chapter start zip file='.$zipFile);
  142. //zip压缩包里面的文件名
  143. $realFilename = $this->realFilename.".".$this->format;
  144. $zipOk = \App\Tools\Tools::zip($zipFile,[$realFilename=>$fileDate]);
  145. if(!$zipOk){
  146. Log::error('export chapter zip fail zip file='.$zipFile);
  147. $this->setStatus(0.99,'export chapter zip fail');
  148. $this->error('export chapter zip fail zip file='.$zipFile);
  149. //TODO 给客户端返回错误状态
  150. return 1;
  151. }
  152. $this->setStatus(0.96,'export chapter zip success');
  153. $bucket = config('mint.attachments.bucket_name.temporary');
  154. $tmpFile = $bucket.'/'. $this->zipFilename ;
  155. Log::debug('upload start filename='.$tmpFile);
  156. $this->setStatus(0.97,'upload start ');
  157. $zipData = file_get_contents($zipFile);
  158. Storage::put($tmpFile, $zipData);
  159. if (App::environment('local')) {
  160. $s3Link = Storage::url($tmpFile);
  161. }else{
  162. try{
  163. $s3Link = Storage::temporaryUrl($tmpFile, now()->addDays(7));
  164. }catch(\Exception $e){
  165. Log::error('export {Exception}',['exception'=>$e]);
  166. return false;
  167. }
  168. }
  169. $this->downloadUrl = $s3Link;
  170. $this->setStatus(1,'export chapter done');
  171. Log::debug('export chapter done, upload',['filename'=>$tmpFile,'url'=>$s3Link] );
  172. unlink($zipFile);
  173. return true;
  174. }
  175. }