java 基于 openOffice 实现在线预览功能

news/2024/11/30 11:28:09/

1 原理

将 office 文档转换为 pdf ,返回文件流给前端实现预览

2 controller 代码

    @ApiOperation(value = "系统文件在线预览接口")@GetMapping("/onlinePreview")public void onlinePreview(@RequestParam("url") String url, HttpServletResponse response) throws Exception {attachmentsService.onlinePreview(url, response);}

3 service 代码

public class AttachmentsService {public void onlinePreview(String url, HttpServletResponse response) throws Exception             {//获取文件类型String[] str = SmartStringUtil.split(url, "\\.");if (str.length == 0) {throw new Exception("文件格式不正确");}String suffix = str[str.length - 1];if (!suffix.equals("txt") && !suffix.equals("doc") && !suffix.equals("docx") && !suffix.equals("xls")&& !suffix.equals("xlsx") && !suffix.equals("ppt") && !suffix.equals("pptx")) {throw new Exception("文件格式不支持预览");}InputStream in = FileConvertUtil.convertNetFile(url, suffix);OutputStream outputStream = response.getOutputStream();//创建存放文件内容的数组byte[] buff = new byte[1024];//所读取的内容使用n来接收int n;//当没有读取完时,继续读取,循环while ((n = in.read(buff)) != -1) {//将字节数组的数据全部写入到输出流中outputStream.write(buff, 0, n);}//强制将缓存区的数据进行输出outputStream.flush();//关流outputStream.close();in.close();}}

4 文件格式转换工具类 FileConvertUtil

package com.eccom.business.utils;import com.artofsolving.jodconverter.DefaultDocumentFormatRegistry;
import com.artofsolving.jodconverter.DocumentConverter;
import com.artofsolving.jodconverter.DocumentFormat;
import com.artofsolving.jodconverter.openoffice.connection.OpenOfficeConnection;
import com.artofsolving.jodconverter.openoffice.connection.SocketOpenOfficeConnection;
import com.artofsolving.jodconverter.openoffice.converter.StreamOpenOfficeDocumentConverter;
import com.eccom.common.exception.CustomException;
import com.eccom.common.utils.StringUtils;
import org.apache.commons.io.FilenameUtils;import java.io.*;
import java.net.*;
import java.util.Base64;
import java.util.Date;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;/*** 文件格式转换工具类*/
public class FileConvertUtil {//    @Value("${baseplatform.file.preview-max-size}")private static int previewMaxSize = 100;/*** 默认转换后文件后缀*/private static final String DEFAULT_SUFFIX = "pdf";/*** openoffice_port*/private static final Integer OPENOFFICE_PORT = 8100;/*** 【office文档转换为PDF(处理本地文件) 】** @param sourcePath: 源文件路径* @param suffix:     源文件后缀* @return java.io.InputStream 转换后文件输入流*/public static InputStream convertLocaleFile(String sourcePath, String suffix) throws Exception {File inputFile = new File(sourcePath);InputStream inputStream = new FileInputStream(inputFile);return covertCommonByStream(inputStream, suffix);}/*** 【office文档转换为PDF(处理网络文件)】** @param netFileUrl: 网络文件路径* @param suffix:     文件后缀* @return java.io.InputStream 转换后文件输入流*/public static InputStream convertNetFile(String netFileUrl, String suffix) throws Exception {// 创建URLnetFileUrl = getEncodeUrl(netFileUrl).replaceAll("\\+", "%20");URL url = new URL(netFileUrl);// 试图连接并取得返回状态码URLConnection urlconn = url.openConnection();urlconn.connect();HttpURLConnection httpconn = (HttpURLConnection) urlconn;int httpResult = httpconn.getResponseCode();if (httpResult == HttpURLConnection.HTTP_OK) {InputStream inputStream = urlconn.getInputStream();//根据响应获取文件大小(M)int size = urlconn.getContentLength() / 1024 / 1024;if (size > previewMaxSize) {throw new CustomException("文件太大,请下载查看");}return covertCommonByStream(inputStream, suffix);}return null;}/*** 【将文件以流的形式转换】** @param inputStream: 源文件输入流* @param suffix:      源文件后缀* @return java.io.InputStream 转换后文件输入流*/public static InputStream covertCommonByStream(InputStream inputStream, String suffix) throws Exception {ByteArrayOutputStream out = new ByteArrayOutputStream();OpenOfficeConnection connection = new SocketOpenOfficeConnection(OPENOFFICE_PORT);connection.connect();DocumentConverter converter = new StreamOpenOfficeDocumentConverter(connection);DefaultDocumentFormatRegistry formatReg = new DefaultDocumentFormatRegistry();DocumentFormat targetFormat = formatReg.getFormatByFileExtension(DEFAULT_SUFFIX);DocumentFormat sourceFormat = formatReg.getFormatByFileExtension(suffix);converter.convert(inputStream, sourceFormat, out, targetFormat);connection.disconnect();return outputStreamConvertInputStream(out);}/*** 【outputStream转inputStream】** @param out:* @return java.io.ByteArrayInputStream*/public static ByteArrayInputStream outputStreamConvertInputStream(final OutputStream out) {ByteArrayOutputStream baos = (ByteArrayOutputStream) out;return new ByteArrayInputStream(baos.toByteArray());}/*** 【文件压缩】网络文件** @param filePath:* @param zipOut:* @return void*/public static void fileToZip(String filePath, ZipOutputStream zipOut) throws IOException {filePath = getEncodeUrl(filePath).replaceAll("\\+", "%20");// 需要压缩的文件File file = new File(filePath);// 获取文件名称,为解决压缩时重复名称问题,对文件名加时间戳处理String fileName = FilenameUtils.getBaseName(URLDecoder.decode(file.getName(), "UTF-8")) + "-"+ String.valueOf(new Date().getTime()) + "."+ FilenameUtils.getExtension(file.getName());InputStream fileInput = getInputStream(filePath);// 缓冲byte[] bufferArea = new byte[1024 * 10];BufferedInputStream bufferStream = new BufferedInputStream(fileInput, 1024 * 10);// 将当前文件作为一个zip实体写入压缩流,fileName代表压缩文件中的文件名称zipOut.putNextEntry(new ZipEntry(fileName));int length = 0;// 最常规IO操作,不必紧张while ((length = bufferStream.read(bufferArea, 0, 1024 * 10)) != -1) {zipOut.write(bufferArea, 0, length);}//关闭流fileInput.close();// 需要注意的是缓冲流必须要关闭流,否则输出无效bufferStream.close();// 压缩流不必关闭,使用完后再关}/*** 【获取网络文件的输入流】** @param filePath: 网络文件路径* @return java.io.InputStream*/public static InputStream getInputStream(String filePath) throws IOException {InputStream inputStream = null;// 创建URLURL url = new URL(filePath);// 试图连接并取得返回状态码URLConnection urlconn = url.openConnection();urlconn.connect();HttpURLConnection httpconn = (HttpURLConnection) urlconn;int httpResult = httpconn.getResponseCode();if (httpResult == HttpURLConnection.HTTP_OK) {inputStream = urlconn.getInputStream();}return inputStream;}/*** 判断汉字的方法,只要编码在\u4e00到\u9fa5之间的都是汉字,中文符号,空格,+** @param c:* @return boolean*/public static boolean isChineseChar(char c) {return String.valueOf(c).matches("[\u4e00-\u9fa5\u3002\uff1b\uff0c\uff1a\u201c\u201d\uff08\uff09\u3001\uff1f\u300a\u300b\\s\\+]");}/*** 得到中文转码后的 url,只转换 url 中的中文字符** @param url:* @return java.lang.String*/public static String getEncodeUrl(String url) throws UnsupportedEncodingException {String resultURL = StringUtils.EMPTY;for (int i = 0; i < url.length(); i++) {char charAt = url.charAt(i);//只对汉字处理if (isChineseChar(charAt)) {String encode = URLEncoder.encode(charAt + "", "UTF-8");resultURL += encode;} else {resultURL += charAt;}}return resultURL;}public static void main(String[] args) {
//        convertNetFile("http://192.168.161.159:8080/profile/upload/2022/03/28/a9b1c5bb-f7a3-478d-afa9-ece99e5b02c6.docx", ".pdf");
//        convert("c:/Users/admin/Desktop/2.pdf", "c:/Users/admin/Desktop/3.pdf");}
}

5 pom 引入依赖

        <!--openoffice--><dependency><groupId>com.artofsolving</groupId><artifactId>jodconverter</artifactId><version>2.2.1</version></dependency><!-- jxls poi --><dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>3.17</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>3.17</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-scratchpad</artifactId><version>3.17</version></dependency><!-- https://mvnrepository.com/artifact/net.sf.jxls/jxls-core --><dependency><groupId>net.sf.jxls</groupId><artifactId>jxls-core</artifactId><version>1.0.6</version></dependency>

6 常见问题

6.1 解决jodconverter 2.2.1 版本不支持docx、xlsx、pptx 转换成PDF格式异常

  • 方案一

解决jodconverter 2.2.1 版本不支持docx、xlsx、pptx 转换成PDF格式异常_gblfy的博客-CSDN博客

com.artofsolving.jodconverter 包下建立 BasicDocumentFormatRegistry 实现 DocumentFormat

package com.artofsolving.jodconverter;import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;/*** 【重写 BasicDocumentFormatRegistry 文档格式】** @author weipeng1* @date 2022-04-01*/
public class BasicDocumentFormatRegistry implements DocumentFormatRegistry {private List/* <DocumentFormat> */ documentFormats = new ArrayList();public void addDocumentFormat(DocumentFormat documentFormat) {documentFormats.add(documentFormat);}protected List/* <DocumentFormat> */ getDocumentFormats() {return documentFormats;}/*** @param extension the file extension* @return the DocumentFormat for this extension, or null if the extension* is not mapped*/@Overridepublic DocumentFormat getFormatByFileExtension(String extension) {if (extension == null) {return null;}//将文件名后缀统一转化if (extension.indexOf("doc") >= 0) {extension = "doc";}if (extension.indexOf("ppt") >= 0) {extension = "ppt";}if (extension.indexOf("xls") >= 0) {extension = "xls";}String lowerExtension = extension.toLowerCase();for (Iterator it = documentFormats.iterator(); it.hasNext(); ) {DocumentFormat format = (DocumentFormat) it.next();if (format.getFileExtension().equals(lowerExtension)) {return format;}}return null;}@Overridepublic DocumentFormat getFormatByMimeType(String mimeType) {for (Iterator it = documentFormats.iterator(); it.hasNext(); ) {DocumentFormat format = (DocumentFormat) it.next();if (format.getMimeType().equals(mimeType)) {return format;}}return null;}
}
  • 方案二

Apache OpenOffice-java调用时的问题总结

目前maven公网仓库中,没有jodconverter-2.2.2.jar,只有jodconverter-2.2.1.jar.而支持新版office和html转换格式的支持,需要2.2.2版本,这个需要自己去下载,并维护到maven私服上。步骤如下:

(1)下载

https://sourceforge.net/projects/jodconverter/?source=typ_redirect 去这个地址下载即可。

(2)上传maven私服

通过步骤1下载下来的是一个.zip的包,解压后在jodconverter-2.2.2\lib目录下可以看到,如下图:

我们可以看到jodconverter-2.2.2.jar包,把这个jar包上传maven私服即可。而这个包里面含有对新版office(.docx .xlsx .pptx)的支持,HTML的支持等。对于juh-3.0.1.jar、ridl-3.0.1.jar、unoil-3.0.1.jar这三个包在maven公网仓库中是可以查到的,所以直接在pom.xml中添加即可。

6.2 乱码问题

 网上有很多攻略,大致讲的是向JDK的编码和linux系统中的编码添加可支持的字体即可。

6.3  OpenOfficeDocumentConverter和StreamOpenOfficeDocumentConverter的区别

(1)最终生成文件权限问题

当Apache OpenOffice服务和java程序部署在同一台服务上时,可以使用OpenOfficeDocumentConverter,但是同时需要注意,使用该类转换的PDF文件用户权限为Apache OpenOffice的启动用户权限。例如,java服务使用较低的权限用户worker启动,而Apache OpenOffice使用root用户启动,那么生成的PDF文件也为root,那么java程序如果对后续生成的PDF文件进行读写等操作时,由于java服务为worker权限,会造成读取不到文件流的问题。而使用StreamOpenOfficeDocumentConverter,是由OpenOffice生成完PDF后,把PDF的流传给java服务,由java服务生成的PDF文件,所以不会产生用户权限的问题

(2)性能问题

OpenOfficeDocumentConverter直接由OpenOffice生成PDF文件,而StreamOpenOfficeDocumentConverter是由OpenOffice把PDF流回传给java服务,有java服务生成。所以OpenOfficeDocumentConverter在性能上更快。但是OpenOfficeDocumentConverter的问题是,不能实现java服务和OpenOffice的高可用性(因为两个服务部署在同一台物理机上)

(3)实现java服务与OpenOffice服务的高可用部署

java服务与OpenOffice服务在同一台物理机时,可以使用OpenOfficeDocumentConverter,因为他转换的更快。如果两个服务不在同一台物理机上,可以使用StreamOpenOfficeDocumentConverter类。


http://www.ppmy.cn/news/706254.html

相关文章

使用openoffice转pdf,详细

近期由于项目的需求&#xff0c;需要word文档转pdf在线预览&#xff0c;由于一直没有接触这块&#xff0c;所以花了将近四天时间才弄明白。 写这篇文章的主要目的是加深自己的记忆&#xff0c;同时方便以后在用。 &#xff08;最近有使用了这个功能&#xff0c;发现这篇文章有…

springboot集成openoffice实现office转PDF在线预览

1、下载官网 OpenOffice 下载地址 Apache OpenOffice - Official Download 2、安装启动服务 window环境: 进入openoffice安装目录&#xff1a;/program/ 开启服务&#xff1a;cmd命令 soffice -headless -accept“socket,host127.0.0.1,port8100;urp;” -nofirststartw…

用java实现,office文件转成pdf文件

实现环境&#xff1a;要求可以在linux环境下运行&#xff0c;开源插件 &#xff0c; 跨平台 以下有五种方法&#xff1a; 结论&#xff1a; office不支持跨平台&#xff0c; aspose收费&#xff0c; 基于pioitext转换后会严重失真&#xff0c; 基于libreOffice不支持插入图…

openOffice + jobConverter 实现Word转PDF。完美解决方案

一.资源准备 openOffice 下载地址&#xff1a;http://www.openoffice.org/download/index.html jobConverter 相关jar包下载地址&#xff1a;https://download.csdn.net/download/mufeng633/10741295 二. 安装openOffice window安装&#xff0c;直接傻瓜式安装即可。 Linux安…

让Java与OpenOffice调情(转)

你在困扰于word文档&#xff0c;Excel文档&#xff0c;各种各样的Office文档处理么&#xff1f; 你在羡慕DotNet程序员可以自如操作MS Office底层接口么&#xff1f; 你在四处翻腾纯java的PDF文件转换方案么&#xff1f; 欢迎来到OpenOffice.Org的世界&#xff0c;在这儿&…

Java利用OpenOffice将word等office文档转换成PDF

OpenOffice.org 是一套跨平台的办公室软件套件&#xff0c;能在 Windows、Linux、MacOS X (X11)、和 Solaris 等操作系统上执行。它与各个主要的办公室软件套件兼容。OpenOffice.org 是自由软件&#xff0c;任何人都可以免费下载、使用、及推广它。 OpenOffice org 的 API 以 U…

JS打印 PDF

JS打印 PDF 利用iframe打印pdf ( 但是这种方法会造成跨域不太好解决 ) goPrint(data) {let iframe document.createElement("IFRAME");iframe.style.visibility "hidden";iframe.src data; //data 是后台返给的pdf线上地址document.body.appendChild(i…

onlyoffice 在线编辑

文章目录 一、拉取镜像,启动二、配置onlyoffice三、编写保存接口四、添加中文字体 一、拉取镜像,启动 要使用onlyoffice的在线编辑,需要从docker拉取镜像 onlyoffice/documentserver docker pull onlyoffice/documentserver启动onlyoffice docker run --name onlyoffice -i …