Java关于word转pdf工具方法的几种解决方案和我遇到一些问题(html中转、jacob、Docx4j)

您所在的位置:网站首页 java调用libreoffice转为pdf无法生成pdf文件 Java关于word转pdf工具方法的几种解决方案和我遇到一些问题(html中转、jacob、Docx4j)

Java关于word转pdf工具方法的几种解决方案和我遇到一些问题(html中转、jacob、Docx4j)

2023-09-01 23:18| 来源: 网络整理| 查看: 265

本文参考文章如下

java转pdf(html转为pdf),解决中文乱码,标签不规范等问题

Java 使用 jacob 将 word 文档转换为 pdf 文件

java实现word生成并转pdf

docx4j word转pdf 中文宋体(中文正文)类型转换乱码

java实现html转pdf,支持中文,css以及中文换行

java项目实现html转pdf的需求(支持中文和CSS样式)

使用 flying-saucer-pdf 实现html转换pdf补充

1、优先学习这些大佬的文章,比我更加优秀,也更加详尽 2、同时因有感网上能查到的资料水准不齐,优秀文章难找,为了避免后来者重复造轮子,也为了提醒自己不断学习,特发此文以总结和整合 3、本人才疏学浅,加之做完需求后没有及时记录,因此只能尽力完成本文,如果各位读者在使用中出现问题或者能解决文中遇到的问题,欢迎回复和讨论

前段时间工作上有一个需求,要将生成的word文档转为pdf的形式,具体要求如下:

1、最好是能够跨系统运行(windows和linux) 2、尽可能少的额外配置且不能安装第三方软件 3、格式不能大乱,要尽可能还原

其实如果不要求跨系统的话很简单的,因此这一需求的难点其实在于跨系统的运行上,还好老大给了两天时间让我慢慢摸,经过一段时间的学(bai)习(du),研(goo)究(gle)和探(stack)讨(overflow),我根据需求整理出了以下思路并实现demo,这其中其中存在的问题我也会标明出来

1、poi直接转(复杂格式下极度混乱,放弃) 2、html中转(文档整体位移) 3、aspose(正式版jar包收费,放弃) 4、jacob(不能跨平台,目前选用的解决方案之一) 5、Docx4j(空格丢失,目前选用的解决方案之一)

ps: 除此之外还有使用第三方软件的解决思路如libreoffice和openoffice,因为需求不允许就不多介绍了

ps2: 同时,如果只是个人学习使用的话我比较推荐aspose的试用版,使用方便,代码简单

html中转

这一思路主要是通过失败的方法1改出来的,方法1格式丢失过于严重,考虑到html对于格式保存较为完好,因此尝试通过html中转 使用saucer来转一定程度上比itext要舒服很多

踩到的坑: 1、当文档字体为“宋体(中文正文)”时,字体似乎是会被识别为Calibri而不是SimSun从而丢失,我尝试在html中进行强转但是没有效果,最终决定将word文件中的“宋体(中文正文)”全都强转为其他可识别字体解决问题 2、特别注意poi和xdocreport的版本,能看出这是比较老的版本了,因为在之后的版本(例如我们常用的poi 4.0)中,poi把xdocreport的类加载路径修改了,但是maven上xdocreport本身因为一直没有更新所以会出现加载失败的问题

**未解决的问题:**生成的pdf文档格式整体向一侧偏移,造成部分文字丢失

先上maven依赖 org.jsoup jsoup 1.11.3 org.apache.commons commons-compress 1.19 org.apache.commons commons-collections4 4.2 org.apache.xmlbeans xmlbeans 3.1.0 com.itextpdf itextpdf 5.5.13 com.itextpdf.tool xmlworker 5.5.13 com.itextpdf itext-asian 5.2.0 org.xhtmlrenderer flying-saucer-pdf 9.0.3 xerces xercesImpl 2.11.0 org.apache.poi poi 3.14 org.apache.poi poi-ooxml-schemas 3.14 org.apache.poi poi-scratchpad 3.14 org.apache.poi poi-ooxml 3.14 fr.opensagres.xdocreport xdocreport 2.0.2 fr.opensagres.xdocreport fr.opensagres.xdocreport.document 2.0.2 fr.opensagres.xdocreport org.apache.poi.xwpf.converter.core 1.0.6 fr.opensagres.xdocreport org.apache.poi.xwpf.converter.pdf 1.0.6 fr.opensagres.xdocreport org.apache.poi.xwpf.converter.xhtml 1.0.6 然后是主要功能代码部分 /** * docx格式word转换为html * * @param fileName * docx文件路径 * @param outPutFile * html输出文件路径 * @param imagePath * 图片路径 * @throws TransformerException * @throws IOException * @throws ParserConfigurationException */ public static void docx2Html(String fileName, String outPutFile,String imagePath) throws TransformerException, IOException, ParserConfigurationException { String fileOutName = outPutFile; long startTime = System.currentTimeMillis(); XWPFDocument document = new XWPFDocument(new FileInputStream(fileName)); List paragraphs = document.getParagraphs(); //1、强转中文格式类型,解决中文消失问题 for (XWPFParagraph paragraph:paragraphs) { List runs = paragraph.getRuns(); for (XWPFRun run:runs) { if(run.getFontFamily()=="Calibri") { run.setFontFamily("SimHei"); } run.setFontFamily("SimSun", XWPFRun.FontCharRange.ascii); } } XHTMLOptions options = XHTMLOptions.create().indent(4); // 导出图片 File imageFolder = new File(imagePath); options.setExtractor(new FileImageExtractor(imageFolder)); // URI resolver options.URIResolver(new FileURIResolver(imageFolder)); File outFile = new File(fileOutName); outFile.getParentFile().mkdirs(); OutputStreamWriter outputStreamWriter = new OutputStreamWriter(new FileOutputStream(outFile), StandardCharsets.UTF_8); XHTMLConverter xhtmlConverter = (XHTMLConverter) XHTMLConverter.getInstance(); xhtmlConverter.convert(document, outputStreamWriter, options); String html = FileUtil.readFileToString(fileOutName, "html"); OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(new File(fileOutName)), StandardCharsets.UTF_8); //2、添加标准html头部,解决中文乱码问题 html=""+html; int i = html.indexOf(""); StringBuffer buffer = new StringBuffer(html); html=buffer.insert(i+6,"\n" + " *\n" + " {\n" + " padding-left: 20pt;\n" + " padding-right: -20pt;\n" + " }\n" + "").toString(); writer.write(html); writer.flush(); writer.close(); System.out.println("Generate " + fileOutName + " with " + (System.currentTimeMillis() - startTime) + " ms."); } /** * docx格式word转换为html * * @param html * html文件 * @param pdfName * pdf文件名 * @param fontDir * 指定字体文件夹路径 * @Param pdfDestPath * pdf输出路径 */ public static void html2pdf(String html, String pdfName, String fontDir,String pdfDestPath) { try { ByteArrayOutputStream os = new ByteArrayOutputStream(); ITextRenderer renderer = new ITextRenderer(); ITextFontResolver fontResolver = (ITextFontResolver) renderer.getSharedContext().getFontResolver(); //遍历添加中文字体库 File f = new File(fontDir); if (f.isDirectory()) { File[] files = f.listFiles((dir, name) -> { String lower = name.toLowerCase(); return lower.endsWith(".otf") || lower.endsWith(".ttf") || lower.endsWith(".ttc"); }); for (int i = 0; i e.printStackTrace(); } } 使用Jacob

这是不考虑跨平台的情况下的解决方案,不论是从配置复杂程度还是从转换的完成度来说都是极好的,几乎没有问题(实际上就是在调用本地office的另存为功能吧) 缺陷 1、不能跨平台 2、要求windows上有office和SaveAsPdf插件 3、需要把jacob的dll文件存放到本地的jre/bin中,一定程度上造成污染

链接:https://pan.baidu.com/s/1eBCOnYkem2XdwXI8d_A7_g 提取码:813q

先上maven依赖 com.hynnet jacob 1.18 再来主要功能代码 private static final int wdFormatPDF = 17; // PDF 格式 public static void word2PDF(String sfileName, String toFileName) { System.out.println("启动 Word..."); long start = System.currentTimeMillis(); ActiveXComponent app = null; Dispatch doc = null; try { app = new ActiveXComponent("Word.Application"); app.setProperty("Visible", new Variant(false)); Dispatch docs = app.getProperty("Documents").toDispatch(); doc = Dispatch.call(docs, "Open", sfileName).toDispatch(); System.out.println("打开文档..." + sfileName); System.out.println("转换文档到 PDF..." + toFileName); File tofile = new File(toFileName); if (tofile.exists()) { tofile.delete(); } Dispatch.call(doc, "SaveAs", toFileName, // FileName wdFormatPDF); 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(); } 使用Docx4j

算是一个比较完善的方案了,没有额外的配置需要添加,也不需要安装什么插件,只要maven导包即可,且支持跨平台操作,转换完善程度尚可

踩到的坑: 1、根据项目不同可能会存在依赖冲突,需要检查maven依赖树解决 2、还是会有中文乱码问题,需要导入中文库,最好是强转一下字体(如方案2中的“宋体(中文正文)这里也会变成乱码”) 3、linux上要求你先有安装中文库才能做字体映射

未解决的问题: 空格丢失,格式略微有点乱

先来maven依赖 com.itextpdf itextpdf 5.4.3 org.docx4j docx4j 6.1.2 org.docx4j docx4j-export-fo 6.0.0 xerces xercesImpl 2.11.0 org.apache.poi poi 4.0.0 org.apache.poi poi-ooxml-schemas 4.0.0 org.apache.poi poi-scratchpad 4.0.0 org.apache.poi poi-ooxml 4.0.0 主要功能代码 ** * word(docx)转pdf * * @param wordPath docx文件路径 * @param pdfOutPath 文件输出路径 */ public static void convertDocx2Pdf(String wordPath, String pdfOutPath) throws IOException { long startTime = System.currentTimeMillis(); OutputStream os = null; InputStream is = null; FileInputStream fis = null; FileOutputStream fos = null; try { fis = new FileInputStream(wordPath); XWPFDocument document = new XWPFDocument(fis); List paragraphs = document.getParagraphs(); for (XWPFParagraph paragraph : paragraphs) { List runs = paragraph.getRuns(); for (XWPFRun run : runs) { run.setFontFamily("宋体"); } } fos = new FileOutputStream(wordPath); document.write(fos); } catch (IOException e) { e.printStackTrace(); } finally { if (fis != null) { fis.close(); } if (fos != null) { fos.flush(); fos.close(); } } try { is = new FileInputStream(new File(wordPath)); WordprocessingMLPackage mlPackage = WordprocessingMLPackage.load(is); Mapper fontMapper = new IdentityPlusMapper(); fontMapper.put("隶书", PhysicalFonts.get("LiSu")); fontMapper.put("宋体", PhysicalFonts.get("SimSun")); fontMapper.put("微软雅黑", PhysicalFonts.get("Microsoft Yahei")); fontMapper.put("黑体", PhysicalFonts.get("SimHei")); fontMapper.put("楷体", PhysicalFonts.get("KaiTi")); fontMapper.put("新宋体", PhysicalFonts.get("NSimSun")); fontMapper.put("华文行楷", PhysicalFonts.get("STXingkai")); fontMapper.put("华文仿宋", PhysicalFonts.get("STFangsong")); fontMapper.put("宋体扩展", PhysicalFonts.get("simsun-extB")); fontMapper.put("仿宋", PhysicalFonts.get("FangSong")); fontMapper.put("仿宋_GB2312", PhysicalFonts.get("FangSong_GB2312")); fontMapper.put("幼圆", PhysicalFonts.get("YouYuan")); fontMapper.put("华文宋体", PhysicalFonts.get("STSong")); fontMapper.put("华文中宋", PhysicalFonts.get("STZhongsong")); mlPackage.setFontMapper(fontMapper); os = new java.io.FileOutputStream(pdfOutPath); //docx4j docx转pdf FOSettings foSettings = Docx4J.createFOSettings(); foSettings.setWmlPackage(mlPackage); Docx4J.toFO(foSettings, os, Docx4J.FLAG_EXPORT_PREFER_XSL); is.close();//关闭输入流 os.close();//关闭输出流 //输出 System.out.println("转换完成" + (System.currentTimeMillis() - startTime) + " ms."); } catch (Exception e) { e.printStackTrace(); try { if (is != null) { is.close(); } if (os != null) { os.close(); } } catch (Exception ex) { ex.printStackTrace(); } } finally { File file = new File(wordPath); if (file != null && file.isFile() && file.exists()) { file.delete(); } } }


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3