recources_catch.dart 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. import 'dart:convert';
  2. import 'dart:io';
  3. import 'dart:typed_data';
  4. import 'dart:ui' as x;
  5. import 'package:fis_lib_pdf/pdf_objects/report/report_helper/report_style_helper.dart';
  6. import 'package:flutter/services.dart';
  7. import 'package:pdf/widgets.dart' as pw;
  8. import 'package:fis_lib_report/report_info/report_info.dart';
  9. import '../pdf_objects/report/report_helper/report_dic.dart';
  10. import 'package:fis_common/js_plateform/js_platform.dart';
  11. ///PDF相关资源缓存
  12. class ResourcesCache {
  13. static final Map<String, pw.Font> pdfCustomFonts = <String, pw.Font>{};
  14. static final Map<String, pw.MemoryImage> _pdfCloudImages =
  15. <String, pw.MemoryImage>{};
  16. static const int C_CACHELENGTH = 100;
  17. static String currentPDFFileKey = "";
  18. static Uint8List? currentGivenPDFBinaryFile;
  19. static Future<bool> Function(String fileName, Uint8List file)? cacheSave;
  20. static Future<Uint8List?> Function(String fileName)? cacheGet;
  21. static final Map<String, Uint8List> _pdfDocs = <String, Uint8List>{};
  22. ///获得默认的字体
  23. static Future<pw.Font> cacheDefaultFont(String fontKey) async {
  24. if (pdfCustomFonts.containsKey(fontKey)) {
  25. return pdfCustomFonts[fontKey]!;
  26. }
  27. const fontName = "NotoSansSC-R.ttf";
  28. Uint8List? pwFontBytes =
  29. cacheGet == null ? null : await cacheGet?.call(fontName);
  30. if (pwFontBytes == null) {
  31. var fontBytes = await rootBundle.load('assets/fonts/$fontName');
  32. var pwFont = pw.Font.ttf(fontBytes);
  33. pdfCustomFonts.addEntries(<String, pw.Font>{fontKey: pwFont}.entries);
  34. if (cacheSave != null) {
  35. // cacheSave?.call(fontName, fontBytes.buffer.asUint8List());
  36. }
  37. return pwFont;
  38. }
  39. return pw.Font.ttf(ByteData.sublistView(pwFontBytes));
  40. }
  41. ///Demo用PDF
  42. static Future<Uint8List> getPDF() async {
  43. var data = await rootBundle.load('assets/222.jpg');
  44. return data.buffer.asUint8List();
  45. }
  46. ///缓存生成的PDF文件
  47. static void cachePDFBinarys(Uint8List pdfBinary) {
  48. _pdfDocs
  49. .addEntries(<String, Uint8List>{currentPDFFileKey: pdfBinary}.entries);
  50. }
  51. ///获取当前缓存PDF二进制文件
  52. static Uint8List? getCachedPDFBinarys() {
  53. return _pdfDocs[currentPDFFileKey];
  54. }
  55. ///清空PDF缓存
  56. static void clearCachedPDF() {
  57. _pdfDocs.clear();
  58. }
  59. ///根据fileToken获得缓存图片
  60. static pw.MemoryImage? getCacheCloudImages(String fileToken) {
  61. return _pdfCloudImages[fileToken];
  62. }
  63. ///缓存ReportInfo下的所有图片资源
  64. static Future<void> cacheAllCloudImages(FReportInfo reportInfo) async {
  65. if (_pdfCloudImages.length == C_CACHELENGTH) {
  66. _pdfCloudImages.clear();
  67. }
  68. var images = <String>[];
  69. await _flattenedAllTheCloudResources(reportInfo.headers, images);
  70. await _flattenedAllTheCloudResources(reportInfo.blocks, images);
  71. await _flattenedAllTheCloudResources(reportInfo.footers, images);
  72. await cacheNetworkResources(images);
  73. }
  74. static Future<void> cacheNetworkResources(List<String> images) async {
  75. for (var i in images) {
  76. if (_pdfCloudImages.containsKey(i)) {
  77. continue;
  78. }
  79. var fileId = _getFileIDFromFileToken(i);
  80. var imageCacheFile = await cacheGet?.call(fileId);
  81. if (imageCacheFile == null) {
  82. var value = await ReportStyleHelper.getMemoryImage(i);
  83. var compressed = await _compressImage(value);
  84. _pdfCloudImages
  85. .addEntries(<String, pw.MemoryImage>{i: compressed}.entries);
  86. await cacheSave?.call(fileId, compressed.bytes);
  87. } else {
  88. var memoryImage = pw.MemoryImage(imageCacheFile);
  89. _pdfCloudImages
  90. .addEntries(<String, pw.MemoryImage>{i: memoryImage}.entries);
  91. }
  92. }
  93. }
  94. static String _getFileIDFromFileToken(String fileToken) {
  95. var tokens = fileToken.split("/");
  96. var fileName = tokens.last.replaceAll("%", "");
  97. return fileName;
  98. }
  99. static Future<void> _flattenedAllTheCloudResources(
  100. List<IBlockElementInfo> infos, List<String> urls) async {
  101. for (var i in infos) {
  102. if (i is InputImageInfo) {
  103. urls.add("");
  104. }
  105. if (i is InputImageListInfo) {
  106. urls.addAll(i.selectedImages);
  107. }
  108. if (i is StaticImageInfo) {
  109. i.source = await _compressStaticImage(i);
  110. }
  111. if (i is RTTableInfo) {
  112. for (var cell in i.cells!.values) {
  113. for (var block in cell.blocks!) {
  114. if (block.elementInfos != null) {
  115. await _flattenedAllTheelementInfos(block.elementInfos!, urls);
  116. }
  117. if (block is InputImageInfo) {
  118. if (block.selectedImage.isNotEmpty) {
  119. urls.add(block.selectedImage);
  120. }
  121. }
  122. if (block is InputImageListInfo) {
  123. urls.addAll(block.selectedImages);
  124. }
  125. }
  126. }
  127. }
  128. if (i.elementInfos != null) {
  129. await _flattenedAllTheelementInfos(i.elementInfos!, urls);
  130. }
  131. }
  132. }
  133. static Future sleep() {
  134. return Future.delayed(const Duration(microseconds: 200), () => {});
  135. }
  136. static Future<void> _flattenedAllTheelementInfos(
  137. List<ElementInfo> infos, List<String> urls) async {
  138. for (var i in infos) {
  139. if (i is InputImageInfo) {
  140. if (i.selectedImage.isNotEmpty) {
  141. urls.add(i.selectedImage);
  142. }
  143. }
  144. if (i is InputImageListInfo) {
  145. urls.addAll(i.selectedImages);
  146. }
  147. if (i is StaticImageInfo) {
  148. i.source = await _compressStaticImage(i);
  149. }
  150. }
  151. }
  152. static _compressStaticImage(StaticImageInfo imageInfo) async {
  153. Uint8List bytes = const Base64Decoder().convert(imageInfo.source!);
  154. var memoryImage = pw.MemoryImage(bytes);
  155. var compressedData = await JSPlateForm.compressBigImage(
  156. imageInfo.source!, memoryImage.width!, memoryImage.height!, 100);
  157. return compressedData;
  158. }
  159. static Future<pw.MemoryImage> _compressImage(Uint8List imagebytes) async {
  160. var memoryImage = pw.MemoryImage(imagebytes);
  161. var imageSize = memoryImage.bytes.length / 1024;
  162. if (imageSize < 200) {
  163. print("PDF render not compress since too small");
  164. return memoryImage;
  165. }
  166. print("PDF render doing jpg compressing");
  167. var sourceBase64 = Base64Encoder().convert(imagebytes);
  168. var compressedData = await JSPlateForm.compressBigImage(
  169. sourceBase64, memoryImage.width!, memoryImage.height!, 100);
  170. var uin8ListData = Base64Decoder().convert(compressedData);
  171. var compresedData = pw.MemoryImage(uin8ListData);
  172. return compresedData;
  173. }
  174. }