OfficeFilePreviewImpl.java 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. package cn.keking.service.impl;
  2. import cn.keking.config.ConfigConstants;
  3. import cn.keking.model.FileAttribute;
  4. import cn.keking.model.ReturnResponse;
  5. import cn.keking.service.FileHandlerService;
  6. import cn.keking.service.FilePreview;
  7. import cn.keking.service.OfficeToPdfService;
  8. import cn.keking.utils.DownloadUtils;
  9. import cn.keking.utils.KkFileUtils;
  10. import cn.keking.utils.OfficeUtils;
  11. import cn.keking.web.filter.BaseUrlFilter;
  12. import org.apache.commons.lang3.exception.ExceptionUtils;
  13. import org.apache.poi.EncryptedDocumentException;
  14. import org.jodconverter.core.office.OfficeException;
  15. import org.springframework.stereotype.Service;
  16. import org.springframework.ui.Model;
  17. import org.springframework.util.ObjectUtils;
  18. import org.springframework.util.StringUtils;
  19. import java.io.IOException;
  20. import java.util.List;
  21. /**
  22. * Created by kl on 2018/1/17.
  23. * Content :处理office文件
  24. */
  25. @Service
  26. public class OfficeFilePreviewImpl implements FilePreview {
  27. public static final String OFFICE_PREVIEW_TYPE_IMAGE = "image";
  28. public static final String OFFICE_PREVIEW_TYPE_ALL_IMAGES = "allImages";
  29. private static final String OFFICE_PASSWORD_MSG = "password";
  30. private final FileHandlerService fileHandlerService;
  31. private final OfficeToPdfService officeToPdfService;
  32. private final OtherFilePreviewImpl otherFilePreview;
  33. public OfficeFilePreviewImpl(FileHandlerService fileHandlerService, OfficeToPdfService officeToPdfService, OtherFilePreviewImpl otherFilePreview) {
  34. this.fileHandlerService = fileHandlerService;
  35. this.officeToPdfService = officeToPdfService;
  36. this.otherFilePreview = otherFilePreview;
  37. }
  38. @Override
  39. public String filePreviewHandle(String url, Model model, FileAttribute fileAttribute) {
  40. // 预览Type,参数传了就取参数的,没传取系统默认
  41. String officePreviewType = fileAttribute.getOfficePreviewType();
  42. boolean userToken = fileAttribute.getUsePasswordCache();
  43. String baseUrl = BaseUrlFilter.getBaseUrl();
  44. String suffix = fileAttribute.getSuffix(); //获取文件后缀
  45. String fileName = fileAttribute.getName(); //获取文件原始名称
  46. String filePassword = fileAttribute.getFilePassword(); //获取密码
  47. boolean forceUpdatedCache=fileAttribute.forceUpdatedCache(); //是否启用强制更新命令
  48. boolean isHtmlView = fileAttribute.isHtmlView(); //xlsx 转换成html
  49. String cacheName = fileAttribute.getCacheName(); //转换后的文件名
  50. String outFilePath = fileAttribute.getOutFilePath(); //转换后生成文件的路径
  51. if (!officePreviewType.equalsIgnoreCase("html")) {
  52. if (ConfigConstants.getOfficeTypeWeb() .equalsIgnoreCase("web")) {
  53. if (suffix.equalsIgnoreCase("xlsx")) {
  54. model.addAttribute("pdfUrl", KkFileUtils.htmlEscape(url)); //特殊符号处理
  55. return XLSX_FILE_PREVIEW_PAGE;
  56. }
  57. if (suffix.equalsIgnoreCase("csv")) {
  58. model.addAttribute("csvUrl", KkFileUtils.htmlEscape(url));
  59. return CSV_FILE_PREVIEW_PAGE;
  60. }
  61. }
  62. }
  63. if (forceUpdatedCache|| !fileHandlerService.listConvertedFiles().containsKey(cacheName) || !ConfigConstants.isCacheEnabled()) {
  64. // 下载远程文件到本地,如果文件在本地已存在不会重复下载
  65. ReturnResponse<String> response = DownloadUtils.downLoad(fileAttribute, fileName);
  66. if (response.isFailure()) {
  67. return otherFilePreview.notSupportedFile(url, model, fileAttribute, response.getMsg());
  68. }
  69. String filePath = response.getContent();
  70. boolean isPwdProtectedOffice = OfficeUtils.isPwdProtected(filePath); // 判断是否加密文件
  71. if (isPwdProtectedOffice && !StringUtils.hasLength(filePassword)) {
  72. // 加密文件需要密码
  73. model.addAttribute("needFilePassword", true);
  74. return EXEL_FILE_PREVIEW_PAGE;
  75. } else {
  76. if (StringUtils.hasText(outFilePath)) {
  77. try {
  78. officeToPdfService.openOfficeToPDF(filePath, outFilePath, fileAttribute);
  79. } catch (OfficeException e) {
  80. if (isPwdProtectedOffice && !OfficeUtils.isCompatible(filePath, filePassword)) {
  81. // 加密文件密码错误,提示重新输入
  82. model.addAttribute("needFilePassword", true);
  83. model.addAttribute("filePasswordError", true);
  84. return EXEL_FILE_PREVIEW_PAGE;
  85. }
  86. return otherFilePreview.notSupportedFile(url, model, fileAttribute, "抱歉,该文件版本不兼容,文件版本错误。");
  87. }
  88. if (isHtmlView) {
  89. // 对转换后的文件进行操作(改变编码方式)
  90. fileHandlerService.doActionConvertedFile(outFilePath);
  91. }
  92. //是否保留OFFICE源文件
  93. if (!fileAttribute.isCompressFile() && ConfigConstants.getDeleteSourceFile()) {
  94. KkFileUtils.deleteFileByPath(filePath);
  95. }
  96. if (userToken || !isPwdProtectedOffice) {
  97. // 加入缓存
  98. fileHandlerService.addConvertedFile(cacheName, fileHandlerService.getRelativePath(outFilePath));
  99. }
  100. }
  101. }
  102. }
  103. if (!isHtmlView && baseUrl != null && (OFFICE_PREVIEW_TYPE_IMAGE.equals(officePreviewType) || OFFICE_PREVIEW_TYPE_ALL_IMAGES.equals(officePreviewType))) {
  104. return getPreviewType(model, fileAttribute, officePreviewType, cacheName, outFilePath, fileHandlerService, OFFICE_PREVIEW_TYPE_IMAGE, otherFilePreview);
  105. }
  106. model.addAttribute("pdfUrl", cacheName);
  107. return isHtmlView ? EXEL_FILE_PREVIEW_PAGE : PDF_FILE_PREVIEW_PAGE;
  108. }
  109. static String getPreviewType(Model model, FileAttribute fileAttribute, String officePreviewType, String pdfName, String outFilePath, FileHandlerService fileHandlerService, String officePreviewTypeImage, OtherFilePreviewImpl otherFilePreview) {
  110. String suffix = fileAttribute.getSuffix();
  111. boolean isPPT = suffix.equalsIgnoreCase("ppt") || suffix.equalsIgnoreCase("pptx");
  112. List<String> imageUrls = null;
  113. try {
  114. imageUrls = fileHandlerService.pdf2jpg(outFilePath,outFilePath, pdfName, fileAttribute);
  115. } catch (Exception e) {
  116. Throwable[] throwableArray = ExceptionUtils.getThrowables(e);
  117. for (Throwable throwable : throwableArray) {
  118. if (throwable instanceof IOException || throwable instanceof EncryptedDocumentException) {
  119. if (e.getMessage().toLowerCase().contains(OFFICE_PASSWORD_MSG)) {
  120. model.addAttribute("needFilePassword", true);
  121. return EXEL_FILE_PREVIEW_PAGE;
  122. }
  123. }
  124. }
  125. }
  126. if (imageUrls == null || imageUrls.size() < 1) {
  127. return otherFilePreview.notSupportedFile(null, model, fileAttribute, "office转图片异常,请联系管理员");
  128. }
  129. model.addAttribute("imgUrls", imageUrls);
  130. model.addAttribute("currentUrl", imageUrls.get(0));
  131. if (officePreviewTypeImage.equals(officePreviewType)) {
  132. // PPT 图片模式使用专用预览页面
  133. return (isPPT ? PPT_FILE_PREVIEW_PAGE : OFFICE_PICTURE_FILE_PREVIEW_PAGE);
  134. } else {
  135. return PICTURE_FILE_PREVIEW_PAGE;
  136. }
  137. }
  138. }