OfficeFilePreviewImpl.java 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  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.OfficeUtils;
  10. import cn.keking.web.filter.BaseUrlFilter;
  11. import org.jodconverter.core.office.OfficeException;
  12. import org.springframework.stereotype.Service;
  13. import org.springframework.ui.Model;
  14. import org.springframework.util.StringUtils;
  15. import java.net.URLEncoder;
  16. import java.util.List;
  17. /**
  18. * Created by kl on 2018/1/17.
  19. * Content :处理office文件
  20. */
  21. @Service
  22. public class OfficeFilePreviewImpl implements FilePreview {
  23. public static final String OFFICE_PREVIEW_TYPE_IMAGE = "image";
  24. public static final String OFFICE_PREVIEW_TYPE_ALL_IMAGES = "allImages";
  25. private static final String FILE_DIR = ConfigConstants.getFileDir();
  26. private final FileHandlerService fileHandlerService;
  27. private final OfficeToPdfService officeToPdfService;
  28. private final OtherFilePreviewImpl otherFilePreview;
  29. public OfficeFilePreviewImpl(FileHandlerService fileHandlerService, OfficeToPdfService officeToPdfService, OtherFilePreviewImpl otherFilePreview) {
  30. this.fileHandlerService = fileHandlerService;
  31. this.officeToPdfService = officeToPdfService;
  32. this.otherFilePreview = otherFilePreview;
  33. }
  34. @Override
  35. public String filePreviewHandle(String url, Model model, FileAttribute fileAttribute) {
  36. // 预览Type,参数传了就取参数的,没传取系统默认
  37. String officePreviewType = fileAttribute.getOfficePreviewType();
  38. String baseUrl = BaseUrlFilter.getBaseUrl();
  39. String suffix = fileAttribute.getSuffix();
  40. String fileName = fileAttribute.getName();
  41. String filePassword = fileAttribute.getFilePassword();
  42. String userToken = fileAttribute.getUserToken();
  43. boolean isHtml = suffix.equalsIgnoreCase("xls") || suffix.equalsIgnoreCase("xlsx") || suffix.equalsIgnoreCase("csv") || suffix.equalsIgnoreCase("xlsm") || suffix.equalsIgnoreCase("xlt") || suffix.equalsIgnoreCase("xltm") || suffix.equalsIgnoreCase("et") || suffix.equalsIgnoreCase("ett") || suffix.equalsIgnoreCase("xlam");
  44. String pdfName = fileName.substring(0, fileName.lastIndexOf(".") + 1) + (isHtml ? "html" : "pdf");
  45. String cacheFileName = userToken == null ? pdfName : userToken + "_" + pdfName;
  46. String outFilePath = FILE_DIR + cacheFileName;
  47. if ( !fileHandlerService.listConvertedFiles().containsKey(pdfName) || !ConfigConstants.isCacheEnabled()) {
  48. // 下载远程文件到本地,如果文件在本地已存在不会重复下载
  49. ReturnResponse<String> response = DownloadUtils.downLoad(fileAttribute, fileName);
  50. if (response.isFailure()) {
  51. return otherFilePreview.notSupportedFile(model, fileAttribute, response.getMsg());
  52. }
  53. String filePath = response.getContent();
  54. /*
  55. * 1. 缓存判断-如果文件已经进行转换过,就直接返回,否则执行转换
  56. * 2. 缓存判断-加密文件基于userToken进行缓存,如果没有就不缓存
  57. */
  58. boolean isCached = false;
  59. boolean isUseCached = false;
  60. boolean isPwdProtectedOffice = false;
  61. if (ConfigConstants.isCacheEnabled()) {
  62. // 全局开启缓存
  63. isUseCached = true;
  64. if (fileHandlerService.listConvertedFiles().containsKey(cacheFileName)) {
  65. // 存在缓存
  66. isCached = true;
  67. }
  68. if (OfficeUtils.isPwdProtected(filePath)) {
  69. isPwdProtectedOffice = true;
  70. if (!StringUtils.hasLength(userToken)) {
  71. // 不缓存没有userToken的加密文件
  72. isUseCached = false;
  73. }
  74. }
  75. } else {
  76. isPwdProtectedOffice = OfficeUtils.isPwdProtected(filePath);
  77. }
  78. if (!isCached) {
  79. // 没有缓存执行转换逻辑
  80. if (isPwdProtectedOffice && !StringUtils.hasLength(filePassword)) {
  81. // 加密文件需要密码
  82. model.addAttribute("needFilePassword", true);
  83. return EXEL_FILE_PREVIEW_PAGE;
  84. } else {
  85. if (StringUtils.hasText(outFilePath)) {
  86. try {
  87. officeToPdfService.openOfficeToPDF(filePath, outFilePath, fileAttribute);
  88. } catch (OfficeException e) {
  89. if (isPwdProtectedOffice && !OfficeUtils.isCompatible(filePath, filePassword)) {
  90. // 加密文件密码错误,提示重新输入
  91. model.addAttribute("needFilePassword", true);
  92. model.addAttribute("filePasswordError", true);
  93. return EXEL_FILE_PREVIEW_PAGE;
  94. }
  95. return otherFilePreview.notSupportedFile(model, fileAttribute, "抱歉,该文件版本不兼容,文件版本错误。");
  96. }
  97. if (isHtml) {
  98. // 对转换后的文件进行操作(改变编码方式)
  99. fileHandlerService.doActionConvertedFile(outFilePath);
  100. }
  101. if (isUseCached) {
  102. // 加入缓存
  103. fileHandlerService.addConvertedFile(cacheFileName, fileHandlerService.getRelativePath(outFilePath));
  104. }
  105. }
  106. }
  107. }
  108. }
  109. if (!isHtml && baseUrl != null && (OFFICE_PREVIEW_TYPE_IMAGE.equals(officePreviewType) || OFFICE_PREVIEW_TYPE_ALL_IMAGES.equals(officePreviewType))) {
  110. return getPreviewType(model, fileAttribute, officePreviewType, baseUrl, cacheFileName, outFilePath, fileHandlerService, OFFICE_PREVIEW_TYPE_IMAGE, otherFilePreview);
  111. }
  112. cacheFileName = URLEncoder.encode(cacheFileName).replaceAll("\\+", "%20");
  113. model.addAttribute("pdfUrl", cacheFileName);
  114. return isHtml ? EXEL_FILE_PREVIEW_PAGE : PDF_FILE_PREVIEW_PAGE;
  115. }
  116. static String getPreviewType(Model model, FileAttribute fileAttribute, String officePreviewType, String baseUrl, String pdfName, String outFilePath, FileHandlerService fileHandlerService, String officePreviewTypeImage, OtherFilePreviewImpl otherFilePreview) {
  117. String suffix = fileAttribute.getSuffix();
  118. boolean isPPT = suffix.equalsIgnoreCase("ppt") || suffix.equalsIgnoreCase("pptx");
  119. List<String> imageUrls = fileHandlerService.pdf2jpg(outFilePath, pdfName, baseUrl);
  120. if (imageUrls == null || imageUrls.size() < 1) {
  121. return otherFilePreview.notSupportedFile(model, fileAttribute, "office转图片异常,请联系管理员");
  122. }
  123. model.addAttribute("imgurls", imageUrls);
  124. model.addAttribute("currentUrl", imageUrls.get(0));
  125. if (officePreviewTypeImage.equals(officePreviewType)) {
  126. // PPT 图片模式使用专用预览页面
  127. return (isPPT ? PPT_FILE_PREVIEW_PAGE : OFFICE_PICTURE_FILE_PREVIEW_PAGE);
  128. } else {
  129. return PICTURE_FILE_PREVIEW_PAGE;
  130. }
  131. }
  132. }