当前位置:   article > 正文

OpenOffice下载及实现pdf在线预览(工作问题记录)_openoffice官网

openoffice官网

        在工作中遇到一个问题,实现word文档的在线预览,网上有很多种方法,我选择的是使用openOffice下载,分享一下我在实现功能中遇到的问题,用于记录也希望帮到别人。

OpenOffice下载

官网下载链接:http://www.openoffice.org/download/

 由于官网是外网下载的比较慢,我这里分享出来我的网盘下载地址,需要的朋友可以下载使用。

百度网盘下载地址:https://pan.baidu.com/s/1Ko-DGEvH2mKET8p4S4xd4Q

提取码:byan

OpenOffice安装

无脑下一步就行了。下载完以后会在桌面有个快捷方式,右击属性查看路径

默认路径为"C:\Program Files (x86)\OpenOffice 4\"

 进入到目录里启动打开cmd命令行启动openoffice服务

start soffice.exe -headless -accept="socket,host=127.0.0.1,port=8100;urp; " -nofirststartwizard

openOffice使用

在pom文件中添加依赖,说一下遇见的问题 jodconverter 这个jar包目前maven仓库里只有2.2.1,2.2.1这个版本的jar包在转换docx,pptx,xlsx三种拓展名文件时,不支持会报错。具体原因和解决方法我会在下面说明。

  1. <!--openoffice-->
  2. <dependency>
  3. <groupId>com.artofsolving</groupId>
  4. <artifactId>jodconverter</artifactId>
  5. <version>2.2.1</version>
  6. </dependency>
  7. <!-- jxls poi -->
  8. <dependency>
  9. <groupId>org.apache.poi</groupId>
  10. <artifactId>poi</artifactId>
  11. <version>3.17</version>
  12. </dependency>
  13. <dependency>
  14. <groupId>org.apache.poi</groupId>
  15. <artifactId>poi-ooxml</artifactId>
  16. <version>3.17</version>
  17. </dependency>
  18. <dependency>
  19. <groupId>org.apache.poi</groupId>
  20. <artifactId>poi-scratchpad</artifactId>
  21. <version>3.17</version>
  22. </dependency>
  23. <!-- https://mvnrepository.com/artifact/net.sf.jxls/jxls-core -->
  24. <dependency>
  25. <groupId>net.sf.jxls</groupId>
  26. <artifactId>jxls-core</artifactId>
  27. <version>1.0.6</version>
  28. </dependency>

创建工具类FileConvertUtil 

  1. public class FileConvertUtil {
  2. // @Value("${baseplatform.file.preview-max-size}")
  3. private static int previewMaxSize = 100;
  4. /**
  5. * 默认转换后文件后缀
  6. */
  7. private static final String DEFAULT_SUFFIX = "pdf";
  8. /**
  9. * openoffice_port
  10. */
  11. private static final Integer OPENOFFICE_PORT = 8100;
  12. /**
  13. * 【office文档转换为PDF(处理本地文件) 】
  14. *
  15. * @param sourcePath: 源文件路径
  16. * @param suffix: 源文件后缀
  17. * @return java.io.InputStream 转换后文件输入流
  18. */
  19. public static InputStream convertLocaleFile(String sourcePath, String suffix) throws Exception {
  20. File inputFile = new File(sourcePath);
  21. InputStream inputStream = new FileInputStream(inputFile);
  22. return covertCommonByStream(inputStream, suffix);
  23. }
  24. /**
  25. * 【office文档转换为PDF(处理网络文件)】
  26. *
  27. * @param netFileUrl: 网络文件路径
  28. * @param suffix: 文件后缀
  29. * @return java.io.InputStream 转换后文件输入流
  30. */
  31. public static InputStream convertNetFile(String netFileUrl, String suffix) throws Exception {
  32. // 创建URL
  33. netFileUrl = getEncodeUrl(netFileUrl).replaceAll("\\+", "%20");
  34. URL url = new URL(netFileUrl);
  35. // 试图连接并取得返回状态码
  36. URLConnection urlconn = url.openConnection();
  37. urlconn.connect();
  38. HttpURLConnection httpconn = (HttpURLConnection) urlconn;
  39. int httpResult = httpconn.getResponseCode();
  40. if (httpResult == HttpURLConnection.HTTP_OK) {
  41. InputStream inputStream = urlconn.getInputStream();
  42. //根据响应获取文件大小(M)
  43. int size = urlconn.getContentLength() / 1024 / 1024;
  44. if (size > previewMaxSize) {
  45. throw new HguException(20001,"文件太大,请下载查看");
  46. }
  47. return covertCommonByStream(inputStream, suffix);
  48. }
  49. return null;
  50. }
  51. /**
  52. * 【将文件以流的形式转换】
  53. *
  54. * @param inputStream: 源文件输入流
  55. * @param suffix: 源文件后缀
  56. * @return java.io.InputStream 转换后文件输入流
  57. */
  58. public static InputStream covertCommonByStream(InputStream inputStream, String suffix) throws Exception {
  59. ByteArrayOutputStream out = new ByteArrayOutputStream();
  60. OpenOfficeConnection connection = new SocketOpenOfficeConnection(OPENOFFICE_PORT);
  61. connection.connect();
  62. DocumentConverter converter = new StreamOpenOfficeDocumentConverter(connection);
  63. DefaultDocumentFormatRegistry formatReg = new DefaultDocumentFormatRegistry();
  64. DocumentFormat targetFormat = formatReg.getFormatByFileExtension(DEFAULT_SUFFIX);
  65. DocumentFormat sourceFormat = formatReg.getFormatByFileExtension(suffix);
  66. converter.convert(inputStream, sourceFormat, out, targetFormat);
  67. connection.disconnect();
  68. return outputStreamConvertInputStream(out);
  69. }
  70. /**
  71. * 【outputStream转inputStream】
  72. *
  73. * @param out:
  74. * @return java.io.ByteArrayInputStream
  75. */
  76. public static ByteArrayInputStream outputStreamConvertInputStream(final OutputStream out) {
  77. ByteArrayOutputStream baos = (ByteArrayOutputStream) out;
  78. return new ByteArrayInputStream(baos.toByteArray());
  79. }
  80. /**
  81. * 【文件压缩】网络文件
  82. *
  83. * @param filePath:
  84. * @param zipOut:
  85. * @return void
  86. */
  87. public static void fileToZip(String filePath, ZipOutputStream zipOut) throws IOException {
  88. filePath = getEncodeUrl(filePath).replaceAll("\\+", "%20");
  89. // 需要压缩的文件
  90. File file = new File(filePath);
  91. // 获取文件名称,为解决压缩时重复名称问题,对文件名加时间戳处理
  92. String fileName = FilenameUtils.getBaseName(URLDecoder.decode(file.getName(), "UTF-8")) + "-"
  93. + String.valueOf(new Date().getTime()) + "."
  94. + FilenameUtils.getExtension(file.getName());
  95. InputStream fileInput = getInputStream(filePath);
  96. // 缓冲
  97. byte[] bufferArea = new byte[1024 * 10];
  98. BufferedInputStream bufferStream = new BufferedInputStream(fileInput, 1024 * 10);
  99. // 将当前文件作为一个zip实体写入压缩流,fileName代表压缩文件中的文件名称
  100. zipOut.putNextEntry(new ZipEntry(fileName));
  101. int length = 0;
  102. // 最常规IO操作,不必紧张
  103. while ((length = bufferStream.read(bufferArea, 0, 1024 * 10)) != -1) {
  104. zipOut.write(bufferArea, 0, length);
  105. }
  106. //关闭流
  107. fileInput.close();
  108. // 需要注意的是缓冲流必须要关闭流,否则输出无效
  109. bufferStream.close();
  110. // 压缩流不必关闭,使用完后再关
  111. }
  112. /**
  113. * 【获取网络文件的输入流】
  114. *
  115. * @param filePath: 网络文件路径
  116. * @return java.io.InputStream
  117. */
  118. public static InputStream getInputStream(String filePath) throws IOException {
  119. InputStream inputStream = null;
  120. // 创建URL
  121. URL url = new URL(filePath);
  122. // 试图连接并取得返回状态码
  123. URLConnection urlconn = url.openConnection();
  124. urlconn.connect();
  125. HttpURLConnection httpconn = (HttpURLConnection) urlconn;
  126. int httpResult = httpconn.getResponseCode();
  127. if (httpResult == HttpURLConnection.HTTP_OK) {
  128. inputStream = urlconn.getInputStream();
  129. }
  130. return inputStream;
  131. }
  132. /**
  133. * 判断汉字的方法,只要编码在\u4e00到\u9fa5之间的都是汉字,中文符号,空格,+
  134. *
  135. * @param c:
  136. * @return boolean
  137. */
  138. public static boolean isChineseChar(char c) {
  139. return String.valueOf(c).matches("[\u4e00-\u9fa5\u3002\uff1b\uff0c\uff1a\u201c\u201d\uff08\uff09\u3001\uff1f\u300a\u300b\\s\\+]");
  140. }
  141. /**
  142. * 得到中文转码后的 url,只转换 url 中的中文字符
  143. *
  144. * @param url:
  145. * @return java.lang.String
  146. */
  147. public static String getEncodeUrl(String url) throws UnsupportedEncodingException {
  148. String resultURL = StringUtils.EMPTY;
  149. for (int i = 0; i < url.length(); i++) {
  150. char charAt = url.charAt(i);
  151. //只对汉字处理
  152. if (isChineseChar(charAt)) {
  153. String encode = URLEncoder.encode(charAt + "", "UTF-8");
  154. resultURL += encode;
  155. } else {
  156. resultURL += charAt;
  157. }
  158. }
  159. return resultURL;
  160. }

controller层

红框这里的参数根据功能需求自己修改就可以了,因为我是要根据从数据表里查出来的数据填充到word模板中下载下来,然后再转成pdf。 所以我的参数里带了我要从前端获取的id和request。如果有现成的word直接转的话,这里给上url(word的本地路径或者网络路径)也是能用的。response是必带的。


service层

service层里的重要代码就是这些,执行完这些就已经实现功能了。

  1. //word文档路径
  2. String url = tempDir+filename;
  3. //获取文件类型
  4. String[] str = url.split( "\\.");
  5. if (str.length == 0) {
  6. throw new Exception("文件格式不正确");
  7. }
  8. String suffix = str[str.length - 1];
  9. if (!suffix.equals("txt") && !suffix.equals("doc") && !suffix.equals("docx") && !suffix.equals("xls")
  10. && !suffix.equals("xlsx") && !suffix.equals("ppt") && !suffix.equals("pptx")) {
  11. throw new Exception("文件格式不支持预览");
  12. }
  13. //处理本地文件
  14. InputStream in = FileConvertUtil.convertLocaleFile(url, suffix);
  15. OutputStream outputStream = response.getOutputStream();
  16. //创建存放文件内容的数组
  17. byte[] buff = new byte[1024];
  18. //所读取的内容使用n来接收
  19. int n;
  20. //当没有读取完时,继续读取,循环
  21. while ((n = in.read(buff)) != -1) {
  22. //将字节数组的数据全部写入到输出流中
  23. outputStream.write(buff, 0, n);
  24. }
  25. //强制将缓存区的数据进行输出
  26. outputStream.flush();
  27. //关流
  28. outputStream.close();
  29. in.close();

上面提到的问题

关于我在上面提到的问题,jodconverter 2.2.1 这个jar包由于不兼容上面提到的三种文件格式,我从网上搜索了好几种解决方案。

1.使用jodconverter-core 这个jar包 网上可以搜到很多相关的文章,想用这种的小伙伴可以去再找找。

2.重写BasicDocumentFormatRegistry类或者DefaultDocumentFormatRegistry类,我们顺着jar包打开找DefaultDocumentFormatRegistry这个类可以发现里面的21种文件格式当中没有我们需要的docx。我这里截出来一部分这个类中的内容。

 下面标红的两个类重写一个就可以了,路径我放到了我的utils里面,建了两个包。

 

BasicDocumentFormatRegistry

 下面我把第一种的源码贴过来,第二种的源码我觉得就不用贴了

  1. package com.hgu.utils.artofsolving.jodconverter;
  2. import com.artofsolving.jodconverter.DocumentFormat;
  3. import com.artofsolving.jodconverter.DocumentFormatRegistry;
  4. import java.util.ArrayList;
  5. import java.util.Iterator;
  6. import java.util.List;
  7. /**
  8. * @description: 重写 BasicDocumentFormatRegistry 文档格式
  9. * @Author: wbw
  10. * @Data: 2022-10-15
  11. **/
  12. public class BasicDocumentFormatRegistry implements DocumentFormatRegistry {
  13. private List/* <DocumentFormat> */ documentFormats = new ArrayList();
  14. public void addDocumentFormat(DocumentFormat documentFormat) {
  15. documentFormats.add(documentFormat);
  16. }
  17. protected List/* <DocumentFormat> */ getDocumentFormats() {
  18. return documentFormats;
  19. }
  20. /**
  21. * @param extension the file extension
  22. * @return the DocumentFormat for this extension, or null if the extension
  23. * is not mapped
  24. */
  25. @Override
  26. public DocumentFormat getFormatByFileExtension(String extension) {
  27. if (extension == null) {
  28. return null;
  29. }
  30. //将文件名后缀统一转化
  31. if (extension.indexOf("doc") >= 0) {
  32. extension = "doc";
  33. }
  34. if (extension.indexOf("ppt") >= 0) {
  35. extension = "ppt";
  36. }
  37. if (extension.indexOf("xls") >= 0) {
  38. extension = "xls";
  39. }
  40. String lowerExtension = extension.toLowerCase();
  41. for (Iterator it = documentFormats.iterator(); it.hasNext(); ) {
  42. DocumentFormat format = (DocumentFormat) it.next();
  43. if (format.getFileExtension().equals(lowerExtension)) {
  44. return format;
  45. }
  46. }
  47. return null;
  48. }
  49. @Override
  50. public DocumentFormat getFormatByMimeType(String mimeType) {
  51. for (Iterator it = documentFormats.iterator(); it.hasNext(); ) {
  52. DocumentFormat format = (DocumentFormat) it.next();
  53. if (format.getMimeType().equals(mimeType)) {
  54. return format;
  55. }
  56. }
  57. return null;
  58. }
  59. }

 DefaultDocumentFormatRegistry

注意!!!,虽然上面上面两个任选一个改动就行,但是另外的一个也要从jar包复制处理到你的目录下。

 3.还有一种更简单的方式,但是我目前没在用,测试的时候试了一下,是可以实现功能的,也是最简便的。让我感觉上面的第二种方式基本没有用,只能说在用第二种方法的时候加深了对这几个类的理解。也是有好处的。

直接说第三种方法:

 看图片就懂了,直接if判断了一下,是docx就把它变成doc,这种方法我试了是可以实现功能的,感兴趣的小伙伴可以试一下!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/428611
推荐阅读
相关标签
  

闽ICP备14008679号