Loading... 最近,公司要求做个文件转pdf的调研报告,于是在网上找了一些实现方法,现在将这些方法做个对比,并记录下来,以后或许有用呢,哈哈。 首先说一下需求,产品要求不能使用第三方软件实现,因为这种实现方式效率不高,所以需要使用“纯[Java](https://so.csdn.net/so/search?q=Java&spm=1001.2101.3001.7020)代码”实现。同时也对跨平台有要求,系统需要运行在linux系统上。综合现阶段发现的方案,决定采用基于Aspose的方式进行实现。 好了,现在先看一下对比的结果: # 各实现对比表 于Windows平台进行测试: ## 测试文件: Word:大小380k、页数225页。内含图片(排版),文字(不同颜色、字体、不同语言)、表格(含样式) Excel:大小297k。内含插入图形、长表格。 PPT:大小539k、内含图片、自定义图形、文字(不同颜色、字体、不同语言)、表格(含样式) | | **基于Openoffice** | **基于libreOffice** | **基于Office** | **基于Pio+Itext** | **基于Aspose** | | ------------------ | -------------------- | -------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | -------------------------------------------------------------------- | | **跨平台性** | 跨平台 | 跨平台 | 仅Windows | 跨平台 | 跨平台 | | **是否安装软件** | 需安装Openoffice | 需安装libreOffice | 需安装Microsoft Office | 否 | 否 | | **是否收费** | 免费 | 免费 | 软件收费(可破解) | 免费 | Jar包收费(可破解) | | **转换Word** | 效率 | 未测 | 首次开启14s。平均8s | 平均10s | 平均10s | | 效果 | 未测 | 支持不同字体、不同文字、支持表格样式。插入图形走样转换后页数相当(225-227)大小相当(380k-360k) | 完全一致转换后大小上升(380k-1.24M) | 字体、表格样式、插入图形失真。(严重失真)转换后页数下降(225-105)大小飙升(380k-1.74M) | 字体样式或无法转换。转换后页数相当(225-224)大小上升(380k-721k) | | **转换Excel** | 效率 | 未测 | 首次开启10s平均4.5s | 异常(Office2016) | 平均5.8s | | 效果 | 未测 | 支持文本颜色。不支持插入图形文本会发生走样转换后大小相当(297k-140k) | 提示异常([Office](https://so.csdn.net/so/search?q=Office&spm=1001.2101.3001.7020) 2016) | 样式失真。excel页面大小过长导致PDF页面被截断,无法显示完整 | 不支持插入图片转换转换后大小减小(297k-196k) | | 转换PPT | 效率 | 未测 | 平均5.3s | 平均4s | 平均15s | | 效果 | 未测 | 几乎完全一致能完美支持表格、自定义图形、图片、文字等大小减小(539k-255k) | 转换成功,无法打开(Office 2016) | 样式严重失真。甚至错误。转换后大小上升(539K-1.3M)页数(225-105) | 几乎完全一致转换后大小减小(539k-398k) | | 优点 | 跨平台 | 文档转换失真小。跨平台 | 转化相对快。对于Office能很好保证少失真,特别是Word文档 | 跨平台 | 转换速度快。支持跨平台。不需要安装软件。失真情况较小 | | 缺点 | 需要安装额外软件 | 需要安装额外软件、效率较低 | 不跨平台需安装OfficeOffice收费Office版本不同效果不同(不稳定性)对JDK有污染 | 样式失真特别严重、效率极低。技术复杂 | 收费(但是可以破解)、即使付费,也不提供源码(官网) | | 评价 | 未知 | 稳定 | 差 | 极差 | 好 | ## 结论 **使用Aspose效果最好。** 各种技术实现起来,综合来说Aspose是比较好的方案,唯一的弊端就是收费。 下面介绍各种方案的具体实现,以及其优缺点,效果图。 # 1)基于openoffice(跨平台、需安装openoffice、复杂格式有错位) ## 原理: 通过第三方工具openoffice,将word、excel、ppt、txt等文件转换为pdf文件 先安装openoffice软件(Windows或[Linux](https://so.csdn.net/so/search?q=Linux&spm=1001.2101.3001.7020)有提供软件) 使用JODConverter的Java的OpenDocument 文件转换器API操作Office系列文件转换为PDF文件 ## 优点: 转换效果比较好。是比较主流的做法 ## 缺点: 服务器需要安装openoffice,比较负重 ## 具体实现: ### 1.下载安装软件 1)Openoffice:Apache下的一个开放免费的文字处理软件 下载地址:http://www.openoffice.org/zh-cn/download/ 2)JODConverter一个Java的OpenDocument 文件转换器,只用到它的jar包 下载地址:https://sourceforge.net/projects/jodconverter/files/JODConverter/ ### 2.启动服务: 打开dos窗口,进入openoffice安装盘符,输入以下代码来启动服务: soffice -headless -accept="socket,host=127.0.0.1,port=8100;urp;" -nofirststartwizard ### 3.Java实现操作转化: Pom.xml依赖 ```html hljs language-xml <!-- https://mvnrepository.com/artifact/com.artofsolving/jodconverter-maven-plugin --><dependency> <groupId>com.artofsolving</groupId> <artifactId>jodconverter-maven-plugin</artifactId> <version>2.2.1</version></dependency></dependency> ``` 转换工具: ```java hljs import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.ConnectException;import java.text.SimpleDateFormat;import java.util.Date; import com.artofsolving.jodconverter.DocumentConverter;import com.artofsolving.jodconverter.openoffice.connection.OpenOfficeConnection;import com.artofsolving.jodconverter.openoffice.connection.SocketOpenOfficeConnection;import com.artofsolving.jodconverter.openoffice.converter.OpenOfficeDocumentConverter;/** * 利用jodconverter(基于OpenOffice服务)将文件(*.doc、*.docx、*.xls、*.ppt)转化为html格式或者pdf格式, * 使用前请检查OpenOffice服务是否已经开启, OpenOffice进程名称:soffice.exe | soffice.bin */public class Doc2HtmlUtil { private static Doc2HtmlUtil doc2HtmlUtil; /** * 获取Doc2HtmlUtil实例 */ public static synchronized Doc2HtmlUtil getDoc2HtmlUtilInstance() { if (doc2HtmlUtil == null) { doc2HtmlUtil = new Doc2HtmlUtil(); } return doc2HtmlUtil; } /*** 转换文件成pdf */ public String file2pdf(InputStream fromFileInputStream, String toFilePath,String type) throws IOException { Date date = new Date(); SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss"); String timesuffix = sdf.format(date); String docFileName = null; String htmFileName = null; if(".doc".equals(type)){ docFileName = "doc_" + timesuffix + ".doc"; htmFileName = "doc_" + timesuffix + ".pdf"; }else if(".docx".equals(type)){ docFileName = "docx_" + timesuffix + ".docx"; htmFileName = "docx_" + timesuffix + ".pdf"; }else if(".xls".equals(type)){ docFileName = "xls_" + timesuffix + ".xls"; htmFileName = "xls_" + timesuffix + ".pdf"; }else if(".ppt".equals(type)){ docFileName = "ppt_" + timesuffix + ".ppt"; htmFileName = "ppt_" + timesuffix + ".pdf"; }else{ return null; } File htmlOutputFile = new File(toFilePath + File.separatorChar + htmFileName); File docInputFile = new File(toFilePath + File.separatorChar + docFileName); if (htmlOutputFile.exists()) htmlOutputFile.delete(); htmlOutputFile.createNewFile(); if (docInputFile.exists()) docInputFile.delete(); docInputFile.createNewFile(); /*** 由fromFileInputStream构建输入文件 */ try { OutputStream os = new FileOutputStream(docInputFile); int bytesRead = 0; byte[] buffer = new byte[1024 * 8]; while ((bytesRead = fromFileInputStream.read(buffer)) != -1) { os.write(buffer, 0, bytesRead); } os.close(); fromFileInputStream.close(); } catch (IOException e) { } // 连接服务 OpenOfficeConnection connection = new SocketOpenOfficeConnection(8100); try { connection.connect(); } catch (ConnectException e) { System.err.println("文件转换出错,请检查OpenOffice服务是否启动。"); } // convert 转换 DocumentConverter converter = new OpenOfficeDocumentConverter(connection); converter.convert(docInputFile, htmlOutputFile); connection.disconnect(); // 转换完之后删除word文件 docInputFile.delete(); return htmFileName; } public static void main(String[] args) throws IOException { Doc2HtmlUtil coc2HtmlUtil = getDoc2HtmlUtilInstance (); File file = null; FileInputStream fileInputStream = null; file = new File("C:/Users/MACHENIKE/Desktop/xxx.doc"); fileInputStream = new FileInputStream(file); coc2HtmlUtil.file2pdf(fileInputStream, "E:/360","doc"); }} ``` 简易实现: ```java hljs public void createPdf(String docFileName) throws IOException{ String path = this.getSession().getServletContext().getRealPath("/")+"attachment/"; File inputFile = new File(path+"/doc/"+ docFileName + ".doc"); File outputFile = new File(path+"/pdf/"+docFileName + ".pdf"); // connect to an OpenOffice.org instance running on port 8100 OpenOfficeConnection connection = new SocketOpenOfficeConnection(8100); connection.connect(); // convert DocumentConverter converter = new OpenOfficeDocumentConverter(connection); converter.convert(inputFile, outputFile); // close the connection connection.disconnect(); } ``` ## 效果:(略) # 2)基于libreoffice(跨平台、需安装libreoffice) ## 原理: 通过第三方工具libreoffice,将word、excel、ppt、txt等文件转换为pdf文件 先安装libreoffice软件(Windows或Linux有提供软件) 使用JODConverter的Java的OpenDocument 文件转换器API操作Office系列文件转换为PDF文件 ## 优点: 转换效果比较好。是比较主流的做法 ## 缺点: 服务器需要安装libreoffice,比较负重。启动服务时效率不是很高 ## 具体实现: ### 1.下载安装软件 1)Openoffice:Apache下的一个开放免费的文字处理软件 下载地址:http://www.openoffice.org/zh-cn/download/ 2)JODConverter一个Java的OpenDocument 文件转换器,只用到它的jar包 下载地址:https://sourceforge.net/projects/jodconverter/files/JODConverter/ ### 2.Java实现 依赖: ```html hljs language-xml <dependency> <groupId>com.itextpdf</groupId> <artifactId>itextpdf</artifactId> <version>5.5.0</version> </dependency> <dependency> <groupId>com.itextpdf</groupId> <artifactId>itext-pdfa</artifactId> <version>5.5.0</version> </dependency> <dependency> <groupId>com.itextpdf</groupId> <artifactId>itext-asian</artifactId> <version>5.2.0</version> </dependency> <dependency> <groupId>com.itextpdf.tool</groupId> <artifactId>xmlworker</artifactId> <version>5.5.0</version> </dependency> <dependency> <groupId>org.jodconverter</groupId> <artifactId>jodconverter-local</artifactId> <version>4.1.0</version> </dependency> <dependency> <groupId>org.xhtmlrenderer</groupId> <artifactId>flying-saucer-pdf</artifactId> <version>9.0.7</version> </dependency> ``` 转换 ```java hljs public class LibreOfficeAndJodconverter { private static OfficeManager officeManager = null; private static final String dirPath = "F:/pdf/"; private static final String LibreOfficeDirPath = "D:/LibreOffice6.1.1.2/LibreOffice"; public static void init() { try { System.out.println("尝试连接已启动的服务..."); ExternalOfficeManagerConfiguration externalProcessOfficeManager = new ExternalOfficeManagerConfiguration(); externalProcessOfficeManager.setConnectOnStart(true); externalProcessOfficeManager.setPortNumber(8100); officeManager = externalProcessOfficeManager.buildOfficeManager(); officeManager.start(); System.out.println("转换服务启动成功!"); } catch (Exception e) { //命令方式:soffice -headless -accept="socket,host=127.0.0.1,port=8100;urp;" -nofirststartwizard System.out.println("启动新服务!"); String libreOfficePath = LibreOfficeDirPath; // 此类在jodconverter-core中3版本中存在,在2.2.2版本中不存在 DefaultOfficeManagerConfiguration configuration = new DefaultOfficeManagerConfiguration(); // libreOffice的安装目录 configuration.setOfficeHome(new File(libreOfficePath)); // 设置端口号 configuration.setPortNumber(8100); // 设置任务执行超时为5分钟 configuration.setTaskExecutionTimeout(1000 * 60 * 5L); // 设置任务队列超时为24小时 configuration.setTaskQueueTimeout(1000 * 60 * 60 * 24L); // 开启转换服务 officeManager = configuration.buildOfficeManager(); officeManager.start(); System.out.println("服务启动成功!"); } } public static void desory() { if (officeManager != null) { officeManager.stop(); } } /** * 合并多个PDF,注意,源pdf中不能含有目的pdf,否则将合并失败*/ public static boolean mergePdfFiles(String[] files, String newfile) { boolean retValue = false; Document document = null; try { document = new Document(new PdfReader(files[0]).getPageSize(1)); PdfCopy copy = new PdfCopy(document, new FileOutputStream(newfile)); document.open(); for (int i = 0; i < files.length; i++) { PdfReader reader = new PdfReader(files[i]); int n = reader.getNumberOfPages(); for (int j = 1; j <= n; j++) { document.newPage(); PdfImportedPage page = copy.getImportedPage(reader, j); copy.addPage(page); } } retValue = true; } catch (Exception e) { e.printStackTrace(); } finally { document.close(); } return retValue; } /** * 开启服务时耗时,需要安装 * 并不是看到什么,就转化为什么样的。有偏移 * * @param args */ public static void main(String[] args) { init(); task(); desory(); } public static void task() { String outputname = "output.pdf"; doDocToFdpLibre("test.docx", outputname); doDocToFdpLibre("ppt.pptx", outputname); doDocToFdpLibre("放弃.xlsx", outputname); doDocToFdpLibre("1.txt", outputname); doDocToFdpLibre("不老梦.jpg", outputname); } public static String doDocToFdpLibre(String inputFileName, String outputFileName) { File inputFile = new File("F:/pdf/" + inputFileName); System.out.println("libreOffice开始转换.............................."); Long startTime = System.currentTimeMillis(); OfficeDocumentConverter converter = new OfficeDocumentConverter(officeManager); File outputFile = new File(dirPath + outputFileName); if (outputFile.exists()) { String uuid1 = UUID.randomUUID().toString(); File temp1 = new File(dirPath + uuid1 + ".pdf"); outputFile.renameTo(temp1); String uuid = UUID.randomUUID().toString(); File temp2 = new File(dirPath + uuid + ".pdf"); converter.convert(inputFile, temp2); String[] files = {dirPath + uuid1 + ".pdf", dirPath + uuid + ".pdf"}; String savepath = dirPath + outputFileName; if (mergePdfFiles(files, savepath)) { temp1.delete(); temp2.delete(); } } else { converter.convert(inputFile, outputFile); } // 转换结束 System.out.println("转换结束。。。。。"); //转换时间 long endTime = System.currentTimeMillis(); long time = endTime - startTime; System.out.println("libreOffice转换所用时间为:" + time); return outputFile.getPath(); }} ``` ## 效果: ### Word文档 除去刚开启,平均8s libreOffice转换所用时间为:14044ms libreOffice转换所用时间为:7147ms libreOffice转换所用时间为:6886ms libreOffice转换所用时间为:7176ms libreOffice转换所用时间为:7001ms libreOffice转换所用时间为:8397ms libreOffice转换所用时间为:8141ms ![](https://img-blog.csdn.net/20181010162523367?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM0MTkwMDIz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70) ![](https://img-blog.csdn.net/20181010162523548?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM0MTkwMDIz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70) ![](https://img-blog.csdn.net/20181010162523468?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM0MTkwMDIz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70) ### Excel ![](https://img-blog.csdn.net/20181010162523967?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM0MTkwMDIz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70) ![](https://img-blog.csdn.net/20181010162523976?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM0MTkwMDIz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70) libreOffice转换所用时间为:10584ms libreOffice转换所用时间为:4534ms libreOffice转换所用时间为:4453ms libreOffice转换所用时间为:4369ms ### ppt转换 libreOffice转换所用时间为:59257ms libreOffice转换所用时间为:52320ms libreOffice转换所用时间为:52571ms ![](https://img-blog.csdn.net/20181010162523942?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM0MTkwMDIz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70) ![](https://img-blog.csdn.net/20181010162523889?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM0MTkwMDIz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70) # 3)基于Microsofe Office(仅Windows、需安装Microsoft Office) ## 原理: 类似于Microsoft Office的“另存为”操作。用Jacob实现对Office系列文件的转换(用jacob(Java COM Bridge)操作office的方式) 需要在Windows下安装Microsoft Office,使用jacob操作Office文件, 并把jacob-x.xx-x64.dll放到java/bin(与java.exe相同)目录下 ## 优点: 能很好的转换,失真小(完美保持原doc格式) ## 缺点: 1需要安装Microsoft Office。 2需要把jacob-x.xx-x64.dll放到java/bin(与java.exe相同)目录下,对JDK目录有污染。 3不支持跨平台 4. Microsoft Office版本不同可能影响转换是否成功 ## 具体实现 ### 1.下载jacob包并加入到环境中: Pom: ```html hljs language-xml <!-- https://mvnrepository.com/artifact/com.hynnet/jacob --> <dependency> <groupId>com.hynnet</groupId> <artifactId>jacob</artifactId> <version>1.18</version> </dependency> ``` ### 2.将jacob包的dll导入到jdk/jre/bin下 (不放会报错:java.lang.NoClassDefFoundError: Could not initialize class com.jacob.com.Dispatch) ![](https://img-blog.csdn.net/20181010162523948?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM0MTkwMDIz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70) 或指定路径:System.getProperty("java.library.path"); ### 3.转换方法: ```java hljs public class Jacob { /** 转PDF格式值 */ static final int WORD_FORMAT_PDF = 17; static final int EXCEL_FORMAT_PDF = 0; static final int PPT_FORMAT_PDF = 32; /*** @Description:根据文件类型转换为pdf */ public static void convert2PDF(String inputFile, String pdfFile) { String suffix = getFileSufix(inputFile); if (suffix.equals("doc") || suffix.equals("docx") || suffix.equals("txt")) { word2PDF(inputFile, pdfFile); } else if (suffix.equals("xls") || suffix.equals("xlsx")) { excel2PDF(inputFile, pdfFile); } else if (suffix.equals("ppt") || suffix.equals("pptx")) { ppt2PDF(inputFile, pdfFile); } else { System.out.println("文件格式不支持转换!"); } } /** * @Description:word转pdf */ private static void word2PDF(String inputFile, String pdfFile) { System.out.println("启动Word..."); long start = System.currentTimeMillis(); ActiveXComponent app = null; Dispatch doc = null; try { // 创建一个word对象 app = new ActiveXComponent("Word.Application"); // 不可见打开word (但默认是不可见的) app.setProperty("Visible", new Variant(false)); // 获取文挡属性 // 调用Documents对象中Open方法打开文档,并返回打开的文档对象Document Dispatch docs = app.getProperty("Documents").toDispatch(); doc = Dispatch.call(docs, "Open", inputFile).toDispatch(); System.out.println("打开文档..." + inputFile); System.out.println("转换文档到PDF..." + pdfFile); File tofile = new File(pdfFile); if(tofile.exists()) { tofile.delete(); } // word保存为pdf格式宏,值为17 Dispatch.call(doc, "SaveAs", pdfFile, WORD_FORMAT_PDF); long end = System.currentTimeMillis(); System.out.println("转换完成..用时:" + (end - start) + "ms."); } catch (Exception e) { System.out.println("========Error:文档转换失败:" + e.getMessage()); } finally { Dispatch.call(doc, "Close", false); System.out.println("关闭文档"); if (app != null) app.invoke("Quit", new Variant[] {}); } //如果没有这句话,winword.exe进程将不会关闭 ComThread.Release(); } /** * @Description:excel转pdf */ private static void excel2PDF(String inputFile, String pdfFile) { System.out.println("启动Excel..."); long start = System.currentTimeMillis(); ActiveXComponent app = null; Dispatch excel = null; try { // 创建一个excel对象 app = new ActiveXComponent("Excel.Application"); // 不可见打开excel app.setProperty("Visible", new Variant(false)); // 获取文挡属性 Dispatch excels = app.getProperty("Workbooks").toDispatch(); // 调用Documents对象中Open方法打开文档,并返回打开的文档对象Document excel = Dispatch.call(excels, "Open", inputFile).toDispatch(); System.out.println("打开文档..." + inputFile); System.out.println("转换文档到PDF..." + pdfFile); File tofile = new File(pdfFile); if(tofile.exists()) { tofile.delete(); } // Excel不能调用SaveAs方法 Dispatch.call(excel, "ExportAsFixedFormat", EXCEL_FORMAT_PDF, pdfFile); long end = System.currentTimeMillis(); System.out.println("转换完成..用时:" + (end - start) + "ms."); } catch (Exception e) { System.out.println("========Error:文档转换失败:" + e.getMessage()); } finally { Dispatch.call(excel, "Close", false); System.out.println("关闭文档"); if (app != null) app.invoke("Quit", new Variant[] {}); } //如果没有这句话,winword.exe进程将不会关闭 ComThread.Release(); } /*** @Description:ppt转pdf */ private static void ppt2PDF(String inputFile, String pdfFile) { System.out.println("启动PPT..."); long start = System.currentTimeMillis(); ActiveXComponent app = null; Dispatch ppt = null; try { // 创建一个ppt对象 app = new ActiveXComponent("PowerPoint.Application"); // 不可见打开(PPT转换不运行隐藏,所以这里要注释掉) // app.setProperty("Visible", new Variant(false)); // 获取文挡属性 Dispatch ppts = app.getProperty("Presentations").toDispatch(); // 调用Documents对象中Open方法打开文档,并返回打开的文档对象Document ppt = Dispatch.call(ppts, "Open", inputFile, true, true, false).toDispatch(); System.out.println("打开文档..." + inputFile); System.out.println("转换文档到PDF..." + pdfFile); File tofile = new File(pdfFile); if(tofile.exists()) { tofile.delete(); } Dispatch.call(ppt, "SaveAs", pdfFile, PPT_FORMAT_PDF); long end = System.currentTimeMillis(); System.out.println("转换完成..用时:" + (end - start) + "ms."); } catch (Exception e) { System.out.println("========Error:文档转换失败:" + e.getMessage()); } finally { Dispatch.call(ppt, "Close"); System.out.println("关闭文档"); if (app != null) app.invoke("Quit", new Variant[] {}); } //如果没有这句话,winword.exe进程将不会关闭 ComThread.Release(); } /*** @Description:获取文件后缀*/ private static String getFileSufix(String fileName) { int splitIndex = fileName.lastIndexOf("."); return fileName.substring(splitIndex + 1); }} ``` ## 效果: ### word文档 成功:用时10821ms 成功:用时9865ms 成功:用时9867ms 成功:用时10481ms ![](https://img-blog.csdn.net/20181010162524147?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM0MTkwMDIz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70) ![](https://img-blog.csdn.net/20181010162524273?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM0MTkwMDIz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70) ### excel: ![](https://img-blog.csdn.net/20181010162524287?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM0MTkwMDIz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70) ![](https://img-blog.csdn.net/20181010162524559?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM0MTkwMDIz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70) ### ppt 成功:用时5265ms 成功:用时3885ms 成功:用时3788ms 成功:用时3817ms ![](https://img-blog.csdn.net/20181010162524640?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM0MTkwMDIz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70) ## 原因探究 报错的原因主要是:office版本问题。开发的时候使用的office2013,PPT不能转pdf。在服务器上安装的office2007,出现了PPT可以转成PDF,excel不能转pdf。卸载了office2007安装office2010后出现了excel能转PDF,PPT不能转PDF。office的版本问题中,world文档不管什么版本都可以成功的转pdf。最后解决的办法:安装2007的excel,2010的PPT,world就能成功的转pdf。注意:office2007不能转pdf,需要安装一个插件。 # 4)POI+IText方式(跨平台、效果差、效率低) ## 原理: 用 poi 将word转换成 html 用IText 将html转换成pdf(要求html中所有标签都必须要闭合,所以这里用jsoup对html进行转换) ## 优点: 不需要安装软件、跨平台 ## 缺点: 1. 失真问题比较大。(格式兼容差) 2. 涉及到中文编码问题。 3. 效率比较低 ## 具体实现 ```java hljs public static String officeToHtml(String sourcePath,String targetPath){ String ext = FileUtils.getFileExt(sourcePath).toLowerCase(); String result = null; switch (ext){ case Consts.OFFICE.DOC: case Consts.OFFICE.DOCX: result = POIWordToHtml.wordToHtml(sourcePath, wordImagePath, targetPath); break; case Consts.OFFICE.XLS: case Consts.OFFICE.XLSX: result = POIExcelToHtml.excelToHtml(sourcePath,targetPath, true); break; case Consts.OFFICE.PPT: case Consts.OFFICE.PPTX: POIPptToHtml.pptToHtml(sourcePath,targetPath); break; default: } return result;}具体工具类暂略 ``` | 具体工具类暂略![](https://img-blog.csdn.net/20181010162525265?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM0MTkwMDIz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70) | | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ## 注意事项: 注意:IText 根据html生成文件的是否会验证html文件是否标准,例如通过poi转换的出来的html文件的一些标签会缺少标签闭合 , 如果用这种html进行转换是没有办法通过itext 的校验的。会出现以下异常 错误: “The element type "meta" must be terminated by the matching end-tag "</meta>".” org.xhtmlrenderer.util.XRRuntimeException: Can't load the XML resource (using TRaX transformer). org.xml.sax.SAXParseException: The element type "meta" must be terminated by the matching end-tag "</meta>". 。 html不规范可采用第三方 jar 包 Jsoup, 直接调用parse方法让html标准 ## 相关博客: [java 实现word 转PDF (采用第三方技术 IText、Poi、Jsoup)](https://blog.csdn.net/ptzrbin/article/details/43449701) ## 效果(很差): ### Word: 耗时大概平均10s左右 耗时:10832ms 耗时:8788ms 耗时:9035ms 耗时:8827ms ![](https://img-blog.csdn.net/2018101016252536?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM0MTkwMDIz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70) ![](https://img-blog.csdn.net/20181010162525713?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM0MTkwMDIz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70) ![](https://img-blog.csdn.net/2018101016252673?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM0MTkwMDIz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70) ### Ppt: 平均大概15s左右 耗时:15932ms 耗时:14835ms 耗时:14884ms 耗时:14889ms ![](https://img-blog.csdn.net/20181010162525708?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM0MTkwMDIz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70) ![](https://img-blog.csdn.net/20181010162525669?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM0MTkwMDIz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70) ### Excel: 平均5.8s 耗时:6263ms 耗时:5858ms 耗时:5698ms 耗时:5546ms ![](https://img-blog.csdn.net/20181010162526357?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM0MTkwMDIz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70) ![](https://img-blog.csdn.net/20181010162526243?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM0MTkwMDIz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70) # 5)Aspose实现(跨平台、付费) ## 优点: 比较完美,低失真。 ## 缺点: 不跨平台、不免费 ## 具体实现: 下载相应jar包。(若不是付费版,将出现水印,限制页数等情况) ### Word: ```java hljs public static boolean getLicense() { boolean result = false; try { InputStream is = new FileInputStream(new File("E:\\IDEA2017\\something2pdf-demo\\src\\main\\resources\\license.xml")); // license.xml应放在..\WebRoot\WEB-INF\classes路径下 License aposeLic = new License(); aposeLic.setLicense(is); result = true; } catch (Exception e) { e.printStackTrace(); } return result; } public static void doc2pdf(String Address) { if (!getLicense()) { // 验证License 若不验证则转化出的pdf文档会有水印产生 return; } try { long old = System.currentTimeMillis(); File file = new File("F:\\pdf/pdf1.pdf"); //新建一个空白pdf文档 FileOutputStream os = new FileOutputStream(file); Document doc = new Document(Address); //Address是将要被转化的word文档 doc.save(os, SaveFormat.PDF);//全面支持DOC, DOCX, OOXML, RTF HTML, OpenDocument, PDF, EPUB, XPS, SWF 相互转换 long now = System.currentTimeMillis(); System.out.println("共耗时:" + ((now - old) / 1000.0) + "秒"); //转化用时 } catch (Exception e) { e.printStackTrace(); } } ``` ### Excel ```java hljs public static boolean getLicense() { boolean result = false; try { InputStream is = Excel2Pdf.class.getClassLoader().getResourceAsStream("xlsxlicense.xml"); // license.xml应放在..\WebRoot\WEB-INF\classes路径下 License aposeLic = new License(); aposeLic.setLicense(is); result = true; } catch (Exception e) { e.printStackTrace(); } return result; } public static void excel2pdf(String Address) { if (!getLicense()) { // 验证License 若不验证则转化出的pdf文档会有水印产生 return; } try { long old = System.currentTimeMillis(); File file = new File("F:\\pdf/pdf2.pdf");// 输出路径 Workbook wb = new Workbook(Address);// 原始excel路径 FileOutputStream fileOS = new FileOutputStream(file); wb.save(fileOS, SaveFormat.PDF); fileOS.close(); long now = System.currentTimeMillis(); System.out.println("共耗时:" + ((now - old) / 1000.0) + "秒\n\n" + "文件保存在:" + file.getPath()); //转化过程耗时 } catch (Exception e) { e.printStackTrace(); } } ``` ### Ppt ```java hljs public static boolean getLicense() { boolean result = false; try { license = Ppt2Pdf.class.getClassLoader().getResourceAsStream("pptlicense.xml");// license路径 License aposeLic = new License(); aposeLic.setLicense(license); result = true; } catch (Exception e) { e.printStackTrace(); } return result; } public static void ppt2pdf(String Address) { // 验证License if (!getLicense()) { return; } try { long old = System.currentTimeMillis(); File file = new File("F:\\pdf/pdf3.pdf");// 输出pdf路径 Presentation pres = new Presentation(Address);//输入pdf路径 FileOutputStream fileOS = new FileOutputStream(file); pres.save(fileOS, SaveFormat.Pdf); fileOS.close(); long now = System.currentTimeMillis(); System.out.println("共耗时:" + ((now - old) / 1000.0) + "秒\n\n" + "文件保存在:" + file.getPath()); //转化过程耗时 } catch (Exception e) { e.printStackTrace(); } } ``` ## Linux下编译运行: javac -cp /usr/local/temp/aspose-words-15.8.0-jdk16.jar Doc2Pdf.java java -cp /usr/local/temp/aspose-words-15.8.0-jdk16.jar:/usr/local/temp Doc2Pdf ## 效果: ### 转换文档: ![](https://img-blog.csdn.net/20181010162526300?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM0MTkwMDIz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70) ![](https://img-blog.csdn.net/20181010162526611?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM0MTkwMDIz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70) 平均4.2s。 共耗时:4.213秒 共耗时:4.2秒 共耗时:4.361秒 共耗时:3.959秒 共耗时:4.235秒 ### 转换ppt: ![](https://img-blog.csdn.net/20181010162527412?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM0MTkwMDIz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70) ![](https://img-blog.csdn.net/20181010162526987?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM0MTkwMDIz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70) ![](https://img-blog.csdn.net/2018101016252778?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM0MTkwMDIz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70) 平均15.5s 共耗时:15.979秒 共耗时:15.212秒 共耗时:14.663秒 ### 转换excel: 平均2.6s ![](https://img-blog.csdn.net/20181010162528109?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM0MTkwMDIz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70) ![](https://img-blog.csdn.net/201810101625289?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM0MTkwMDIz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70) 共耗时:2.67秒 共耗时:2.524秒 共耗时:2.741秒 共耗时:2.7秒 最后修改:2022 年 03 月 15 日 © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 0 如果觉得我的文章对你有用,请随意赞赏