GenPDFService.cs 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. using StackExchange.Redis;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7. using TEAMModelOS.SDK.DI;
  8. using TEAMModelOS.SDK.Extension;
  9. namespace TEAMModelOS.SDK.Models.Service
  10. {
  11. public class GenPDFService
  12. {
  13. /// <summary>
  14. /// https://github.com/wuxue107/bookjs-eazy https://github.com/wuxue107/screenshot-api-server
  15. /// </summary>
  16. /// <param name="azureServiceBus"></param>
  17. /// <param name="azureRedis"></param>
  18. /// <param name="data"></param>
  19. /// <returns></returns>
  20. public async Task<string> AddGenPdfQueue(AzureServiceBusFactory azureServiceBus , AzureRedisFactory azureRedis, GenPDFData data)
  21. {
  22. long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  23. List<PDFGenRedis> genRedis = new List<PDFGenRedis>();
  24. List<PDFGenRedis> dbgenRedis = new List<PDFGenRedis>();
  25. HashEntry[] datas = await azureRedis.GetRedisClient(8).HashGetAllAsync($"PDFGen:{data.sessionId}");
  26. if (datas!= null && datas.Length > 0)
  27. {
  28. foreach (var item in datas)
  29. {
  30. dbgenRedis.Add(item.Value.ToString().ToObject<PDFGenRedis>());
  31. }
  32. }
  33. int countProcess= 0;
  34. foreach (var item in data.datas)
  35. {
  36. var dbData = dbgenRedis.Find(x => x.id.Equals(item.id));
  37. if (dbData!=null)
  38. {
  39. if (dbData.status==0|| dbData.status==1)
  40. {
  41. //不变的
  42. countProcess+=1;
  43. }
  44. else
  45. {
  46. //需要变更的
  47. dbData.status = 0;
  48. dbData.cost=0;
  49. dbData.join= now;
  50. dbData.wait=0;
  51. genRedis.Add(dbData);
  52. }
  53. }
  54. else {
  55. genRedis.Add(new PDFGenRedis { id = item.id, status=0, cost=0, wait=0, join=now });
  56. }
  57. }
  58. //过期时间 当前个数+ reddis的个数
  59. foreach (var item in genRedis)
  60. {
  61. countProcess+=1;
  62. await azureRedis.GetRedisClient(8).HashSetAsync($"PDFGen:{data.sessionId}", item.id, item.ToJsonString());
  63. }
  64. long expire = (data.delay+data.timeout) * countProcess ;
  65. var tiemSpan = TimeSpan.FromMilliseconds(expire);
  66. await azureRedis.GetRedisClient(8).KeyExpireAsync($"PDFGen:{data.sessionId}", tiemSpan);
  67. return null;
  68. }
  69. }
  70. public class GenPDFData
  71. {
  72. public string pageUrl { get; set; }
  73. public long timeout { get; set; } = 30000;
  74. public long delay { get; set; } = 2000;
  75. public string orientation { get; set; }
  76. public string pageSize { get; set; }
  77. public string pageWidth { get; set; }
  78. public string pageHeight { get; set; }
  79. /// <summary>
  80. /// 生成会话id, 活动id
  81. /// </summary>
  82. public string sessionId { get; set; }
  83. public List<PDFData> datas { get; set; } = new List<PDFData>();
  84. }
  85. public record PDFData{
  86. /// <summary>
  87. /// 学生id
  88. /// </summary>
  89. public string id { get; set; }
  90. /// <summary>
  91. /// 数据链接
  92. /// </summary>
  93. public string url { get; set; }
  94. }
  95. /// <summary>
  96. /// redis 存储数据,超时时间设置为status=0 的count timeout* count+ delay*count
  97. /// </summary>
  98. public record PDFGenRedis
  99. {
  100. /// <summary>
  101. /// 学生id
  102. /// </summary>
  103. public string id { get; set; }
  104. /// <summary>
  105. /// 0 未执行,1 执行中,2 执行成功,3 执行失败,4超时,5 取消
  106. /// </summary>
  107. public int status { get; set; } = 0;
  108. /// <summary>
  109. /// 执行生成 毫秒
  110. /// </summary>
  111. public long cost { get; set;}
  112. /// <summary>
  113. /// 等候时间
  114. /// </summary>
  115. public long wait { get; set;}
  116. /// <summary>
  117. /// 加入时间
  118. /// </summary>
  119. public long join { get; set; }
  120. }
  121. /// <summary>
  122. /// // 拼接上接口的前缀 http://localhost:3000/ 就是完整PDF地址
  123. // http://localhost:3000/pdf/1614458263411-glduu.pdf
  124. // 拼接上接口的前缀 http://localhost:3000/download/可以就可生成在浏览器上的下载链接
  125. // http://localhost:3000/download/pdf/1614458263411-glduu.pdf
  126. // 拼接上http://localhost:3000/static/js/pdfjs/web/viewer.html?file=/pdf/1614458263411-glduu.pdf
  127. // 可使用pdfjs库进行预览
  128. //
  129. //## -e MAX_BROWSER=[num] 环境变量可选,最大的puppeteer实例数,忽略选项则默认值:1 , 值auto:[可用内存]/200M
  130. //## -e PDF_KEEP_DAY=[num] 自动删除num天之前产生的文件目录,默认0: 不删除文件
  131. //docker run -p 13000:3000 -td --rm -e MAX_BROWSER=2 -e PDF_KEEP_DAY=1 -v ${PWD}:/screenshot-api-server/public --name=screenshot-api-server wuxue107/screenshot-api-server
  132. /// </summary>
  133. public record PDFGenQueue
  134. {
  135. /// <summary>
  136. /// 学生id
  137. /// </summary>
  138. public string id { get; set; }
  139. /// <summary>
  140. /// 数据装载后的页面 要制作为PDF的网页 (pageUrl 、html 参数二选一)
  141. /// </summary>
  142. public string pageUrl { get; set; }
  143. /// <summary>
  144. /// 要截图的网页HTML (pageUrl 、html 参数二选一) "html" : "<div>bookjs-eazy</div>",
  145. /// </summary>
  146. public string html { get; set; }
  147. /// <summary>
  148. /// 超时时间
  149. /// </summary>
  150. public long timeout { get; set; } = 30000;
  151. /// <summary>
  152. /// 页面完成后(checkPageCompleteJs返回为true后)延迟的时间,可选,默认:0
  153. /// </summary>
  154. public long delay { get; set; } = 2000;
  155. /// <summary>
  156. /// // 检查页面是否渲染完成的js表达式,可选,默认: "true"
  157. /// </summary>
  158. public bool checkPageCompleteJs { get; set; }
  159. /// <summary>
  160. /// 生成会话id, 活动id
  161. /// </summary>
  162. public string sessionId { get; set; }
  163. }
  164. }