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. if($this->debug){
  105. $dir = "export/{$type}/".$this->format."/".$this->zipFilename."/";
  106. $filename = $dir.$outputFilename.'.html';
  107. Log::debug('save',['filename'=>$filename]);
  108. foreach ($tex as $key => $section) {
  109. Storage::disk('local')->append($filename, $section['content']);
  110. }
  111. }
  112. $this->setStatus(0.95,'export content done. tex count='.count($tex));
  113. //upload
  114. $fileDate = '';
  115. switch ($this->format) {
  116. case 'tex':
  117. $data = Export::ToPdf($tex);
  118. if($data['ok']){
  119. $this->info($data['content-type']);
  120. $fileDate = $data['data'];
  121. }else{
  122. $this->error($data['code'].'-'.$data['message']);
  123. }
  124. break;
  125. case 'html':
  126. $file = array();
  127. foreach ($tex as $key => $section) {
  128. $file[] = $section['content'];
  129. }
  130. $fileDate = implode('',$file);
  131. break;
  132. }
  133. $zipDir = storage_path('app/export/zip');
  134. if(!is_dir($zipDir)){
  135. $res = mkdir($zipDir,0755,true);
  136. if(!$res){
  137. Log::error('mkdir fail path='.$zipDir);
  138. return 1;
  139. }
  140. }
  141. $zipFile = $zipDir.'/'. $outputFilename .'.zip';
  142. Log::debug('export chapter start zip file='.$zipFile);
  143. //zip压缩包里面的文件名
  144. $realFilename = $this->realFilename.".".$this->format;
  145. $zipOk = \App\Tools\Tools::zip($zipFile,[$realFilename=>$fileDate]);
  146. if(!$zipOk){
  147. Log::error('export chapter zip fail zip file='.$zipFile);
  148. $this->setStatus(0.99,'export chapter zip fail');
  149. $this->error('export chapter zip fail zip file='.$zipFile);
  150. //TODO 给客户端返回错误状态
  151. return 1;
  152. }
  153. $this->setStatus(0.96,'export chapter zip success');
  154. $bucket = config('mint.attachments.bucket_name.temporary');
  155. $tmpFile = $bucket.'/'. $this->zipFilename ;
  156. Log::debug('upload start filename='.$tmpFile);
  157. $this->setStatus(0.97,'upload start ');
  158. $zipData = file_get_contents($zipFile);
  159. Storage::put($tmpFile, $zipData);
  160. if (App::environment('local')) {
  161. $s3Link = Storage::url($tmpFile);
  162. }else{
  163. try{
  164. $s3Link = Storage::temporaryUrl($tmpFile, now()->addDays(7));
  165. }catch(\Exception $e){
  166. Log::error('export {Exception}',['exception'=>$e]);
  167. return false;
  168. }
  169. }
  170. $this->downloadUrl = $s3Link;
  171. $this->setStatus(1,'export chapter done');
  172. Log::debug('export chapter done, upload filename='.$tmpFile);
  173. unlink($zipFile);
  174. return true;
  175. }
  176. }