近期做的一个功能,将Word转为HTML,因为这一块是盲点,所以代码借鉴了网上的某个大佬。

详情移步到:https://blog.csdn.net/qq_18219457/article/details/97943035。这篇文章只为填坑。

一、docx文件转HTML

1、乱码问题:读写文件时必须将编码格式统一“utf-8”。否则你会发现,单独打开文件时正常,用浏览器预览时就乱码了。从代码中仔细查找,一定有某个地方没有设置编码格式。

2、docx文件相当于Word的压缩文件。使用压缩工具打开方式,可以看到文件中的xml文件。如图:

其中document.xml文件就是docx文件的主文件,可以看出文件中的详细内容,如:文本、图片、公式以及样式。

详情移步:https://blog.csdn.net/qq_18219457/article/details/98963136

3、转换代码:这里只获取文件中的文本内容(包括表格)、图片、公式。具体还有没有别的需求,还待测试,先做一个记录。

文本中如果有上下标,不会当作公式处理,必须手动转换。

VerticalAlign vertAlign =  run.getSubscript();

int sort = vertAlign.getValue();

sort分别代表:1、BASELINE 指定父运行中的文本应位于基线处,并以与周围文本相同的大小显示。2、SUBSCRIPT 指定此文本应为上标。 3、SUPERSCRIPT 下标。

类似上下标的还有下划线等等。方法可参考文档:http://poi.apache.org/apidocs/dev/org/apache/poi/xwpf/usermodel/XWPFRun.html

/*** docx文件转HTML* @param storeFile* @param relPath* @return*/public synchronized static String docxToHtml(File storeFile,String relPath) {String htmlUrl = "";try {XWPFDocument document = new XWPFDocument(new FileInputStream(storeFile));List<IBodyElement> elements = document.getBodyElements();StringBuffer text = new StringBuffer();String s = UUID.randomUUID().toString();// 去掉-String aString = s.substring(0,8)+s.substring(9,13)+s.substring(14,18)+s.substring(19,23)+s.substring(24);String htmlName = aString + ".html";htmlUrl = relPath +"/"+ htmlName;// 判断HTML文件是否存在File htmlFile = new File(CommonConstants.fileRoot + relPath +"/"+htmlName);//创建图片文件夹String imgPath = CommonConstants.fileRoot+relPath +"/"+aString+ "/image";// 生成HTML文件上级文件夹File folder = new File(imgPath);if (!folder.exists()) {folder.mkdirs();}//构造ImageParseImageParse imageParse = new ImageParse(imgPath, "");imageParse.setRelUrl(relPath+"/"+aString+ "/image/");if(elements != null){for (IBodyElement element : elements) {if (element instanceof XWPFParagraph) {// 段落text.append(getParagraphText((XWPFParagraph) element,document,imgPath,imageParse));}else if (element instanceof XWPFTable) {// 表格text.append(getTabelText((XWPFTable) element,document,imgPath,imageParse));}}map.clear();//自动编号处理完后需要清空}FileOutputStream outputStream = new FileOutputStream(htmlFile);OutputStreamWriter out = new OutputStreamWriter(outputStream,"UTF-8");out.write(text.toString());out.close();} catch (Exception e) {e.printStackTrace();map.clear();//若出现异常自动编号也需要清空}return htmlUrl;}

4、数学公式处理:

常见的数学公式由两种格式。

一种是在WPS中编辑,这种公式可以转换成图片。目前我了解到最好的方式就是转成svg格式图片。svg格式是矢量图片,放大缩小不会因屏幕分辨率差异造成模糊。屏幕展示效果好。

另一种是由微软的Word编辑,这种公式生成了一种omml标签,可以转换成mathML公式。目前部分浏览器已经支持mathML标签,如火狐等。但一些主流的浏览器还无法直接显示,可以前台引入一些插件也是可以显示的。也可以转成图片,但是我只能转成png格式,不知道svg图片怎么生成,希望有知道的大佬指点一下。

公式一、

/*** 获取图片格式公式 * @param run* @param runNode* @return* @throws Exception*/
private static String getMath(XWPFRun run, Node runNode,String imgPath) throws Exception {StringBuffer math = new StringBuffer("<img");Node objectNode = getChildNode(runNode, "w:object");if (objectNode == null) {return "";}Node shapeNode = getChildNode(objectNode, "v:shape");if (shapeNode == null) {return "";}Node imageNode = getChildNode(shapeNode, "v:imagedata");if (imageNode == null) {return "";}Node binNode = getChildNode(objectNode, "o:OLEObject");if (binNode == null) {return "";}XWPFDocument word = run.getDocument();NamedNodeMap shapeAttrs = shapeNode.getAttributes();// 图片在Word中显示的宽高String style = shapeAttrs.getNamedItem("style").getNodeValue();NamedNodeMap imageAttrs = imageNode.getAttributes();// 图片在Word中的IDString imageRid = imageAttrs.getNamedItem("r:id").getNodeValue();// 获取图片信息PackagePart imgPart = word.getPartById(imageRid);String imgUrl = imgPart.getPartName().getName();String imgName = imgUrl.substring(imgUrl.lastIndexOf("/"),imgUrl.lastIndexOf("."));//图片名称//保存公式图片InputStream in = imgPart.getInputStream();FileOutputStream out = new FileOutputStream(new File(imgPath +"/"+ imgName+".wmf"));;byte[] buffer=new byte[2097152];int readByte = 0;while((readByte = in.read(buffer)) != -1){out.write(buffer, 0, readByte);}in.close();out.close();//将.wmf格式图片转成svgconvertSVG(imgPath+"/"+imgName+".wmf");imgName += ".svg";NamedNodeMap binAttrs = binNode.getAttributes();// 公式二进制文件在Word中的IDString binRid = binAttrs.getNamedItem("r:id").getNodeValue();// 获取二进制文件PackagePart binPart = word.getPartById(binRid);//保存公式源文件, 以供后续使用File file=new File(imgPath.substring(0, imgPath.lastIndexOf("/image"))+"/math_source");if(!file.exists()){//如果文件夹不存在file.mkdir();//创建文件夹}InputStream inBin = binPart.getInputStream();FileOutputStream outBin = new FileOutputStream(new File(file.getPath()+binPart.getPartName().getName().substring(binPart.getPartName().getName().lastIndexOf("/"), binPart.getPartName().getName().length())));byte[] bufferBin=new byte[2097152];int readByteBin = 0;while((readByte = inBin.read(bufferBin)) != -1){outBin.write(buffer, 0, readByteBin);}inBin.close();outBin.close();String relPath = imgPath.replaceFirst(CommonConstants.fileRoot, "");math.append(" src=\""+relPath+imgName+"\"");math.append(" style=\""+style+"\"/> ");return math.toString();
}
/*** 获取一个子标签对象* @param node* @param nodeName* @return*/
private static Node getChildNode(Node node, String nodeName) {if (!node.hasChildNodes()) {return null;}NodeList childNodes = node.getChildNodes();for (int i = 0; i < childNodes.getLength(); i++) {Node childNode = childNodes.item(i);if (nodeName.equals(childNode.getNodeName())) {return childNode;}childNode = getChildNode(childNode, nodeName);if (childNode != null) {return childNode;}}return null;
}
/*** 将wmf文件转换成svg图片* @param path wmf文件路径* @return 转换后的文件路径*/
public static String convertSVG(String path) {try {String svgFile = StringUtils.replace(path, "wmf", "svg");wmfToSvg(path, svgFile);return svgFile;} catch (Exception e) {e.printStackTrace();}return null;
}/*** 将wmf转换为svg* * @param src* @param dest*/
public static void wmfToSvg(String src, String dest) {boolean compatible = false;try {InputStream in = new FileInputStream(src);WmfParser parser = new WmfParser();final SvgGdi gdi = new SvgGdi(compatible);parser.parse(in, gdi);Document doc = gdi.getDocument();OutputStream out = new FileOutputStream(dest);if (dest.endsWith(".svgz")) {out = new GZIPOutputStream(out);}output(doc, out);} catch (Exception e) {e.printStackTrace();}
}
private static void output(Document doc, OutputStream out) throws Exception {TransformerFactory factory = TransformerFactory.newInstance();Transformer transformer = factory.newTransformer();transformer.setOutputProperty(OutputKeys.METHOD, "xml");transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");transformer.setOutputProperty(OutputKeys.INDENT, "yes");transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC,"-//W3C//DTD SVG 1.0//EN");transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM,"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd");transformer.transform(new DOMSource(doc), new StreamResult(out));out.flush();out.close();
}

公式二、

//Office的OMML公式转MathML插件资源文件private static File stylesheet = new File(CommonConstants.fileRoot+"/OMML2MML.XSL");private static StreamSource streamSource = new StreamSource(stylesheet);/*** 直接转node有等号会出问题,先转成xml的string,再转成mathML的字符串** @param node* @return* @throws Exception */private static String getMathMLFromNode(Node node) throws Exception {String s = W3cNodeUtil.node2XmlStr(node);// encoding utf-16String mathML = W3cNodeUtil.xml2Xml(s, streamSource);mathML = mathML.replaceAll("xmlns:m=\"http://schemas.openxmlformats.org/officeDocument/2006/math\"", "");mathML = mathML.replaceAll("xmlns:mml", "xmlns");mathML = mathML.replaceAll("mml:", "");return mathML;}/*** MathML转PNG* @param node* @param imageParser* @return* @throws Exception */public static String convertOmathToPng(XmlObject xmlObject, ImageParse imageParser) {Document document = null;try {String mathMLStr = getMathMLFromNode(xmlObject.getDomNode());document = W3cNodeUtil.xmlStr2Node(mathMLStr, "utf-16");return documentToImageHTML(document, imageParser);} catch (Exception e) {e.printStackTrace();}return null;}/*** Document转PNG* @param node* @param imageParser* @return*/private static String documentToImageHTML(Document node, ImageParse imageParser) {try {Converter mathMLConvert = Converter.getInstance();LayoutContextImpl localLayoutContextImpl = new LayoutContextImpl(LayoutContextImpl.getDefaultLayoutContext());localLayoutContextImpl.setParameter(Parameter.MATHSIZE, 64);ByteArrayOutputStream os = new ByteArrayOutputStream();Dimension den = mathMLConvert.convert(node, os, "image/png", localLayoutContextImpl);String pngName = imageParser.parse(os.toByteArray(), ".png");os.close();double height = den.getHeight()*0.17;return "<img src=\""+ imageParser.getRelUrl() + pngName + "\"  style=\"vertical-align: text-bottom; height:"+height+"pt;\"/>";} catch (IOException e) {e.printStackTrace();logger.error("OmmlUtils.documentToImageHTML", e);} catch (Exception e) {e.printStackTrace();}return null;}

5、图片处理,略。详情:https://blog.csdn.net/qq_18219457/article/details/98184621

二、doc格式转HTML

https://blog.csdn.net/qq_18219457/article/details/97943035

doc文件格式转换HTML后会生成标签样式等。如果想要纯净数据,就不能用doc格式编辑了。虽然已有完善的解析工具,但是现在office默认新建Word都是docx格式了。以后doc格式的文件会越来越少,会慢慢弃用。所以不再放重点!

新人笔记。如果有什么不对,望大佬指正。

使用POI将Word转HTML遇到的问题相关推荐

  1. Java:Java的jar包之POI的简介、安装、使用方法(基于POI将Word、Excel、PPT转换为html)之详细攻略

    Java:Java的jar包之POI的简介.安装.使用方法(基于POI的转换-Word.Excel.Ppt等转html)之详细攻略 目录 POI的简介 1.基本功能 POI的安装 POI的使用方法(基 ...

  2. POI获取WORD信息

    最近由于工作需要,调研了一下关于poi获取word字体信息方面的方法,在这里mark一下. 首先word格式分为doc和docx,分别利用HWPFDocument和XWPFDocument对文档进行解 ...

  3. POI读取word文件,(支持HSSF和XSSF两种方式)

    POI读取word文件,(支持HSSF和XSSF两种方式) 参考:HSSF,XSSF,SXSSF三种方式 1.引用maven(版本必须一致) <dependency><groupId ...

  4. 使用POI读取word文档

    使用POI 读取word 文档(word 2003和2007) 最近在给客户做系统的时候,用户提出需求,要能够导入 word 文件,现在 microsoft word 有好几个版本 97.2003.2 ...

  5. java poi读取word中附件_java poi word读取

    用 poi 读取word文件 . 老是报错 org.apache.poi.poifs.filesystem.NotOLE2FileException: Invalid header signature ...

  6. java poi读取word中附件_java用poi实现对word读取和修改操作

    java编程要实现对word的操作没有vb那种编程语言来得容易,得借助一些开源组件,其中就包括jacob.poi等, 而poi应用得最为广泛,对word2003和2007的读和写word操作都十分方便 ...

  7. java如何解析word大纲_Java POI 解析word文档

    实现步骤: 1.poi实现word转html 2.模型化解析html 3.html转Map数组 Map数组(数组的操作处理不做说明) 1.导jar包. 2.代码实现 package com.web.o ...

  8. apache poi使用例_使用java Apache poi 根据word模板生成word报表例子

    [实例简介] 使用java Apache poi 根据word模板生成word报表 仅支持docx格式的word文件,大概是word2010及以后版本,doc格式不支持. 使用说明:https://b ...

  9. JAVA POI处理WORD

    JAVA POI处理WORD 转载:http://w26.iteye.com/blog/974442 JavaApacheSVN 关键字:POI WORD HWPF WORD文本组成:文本.图.表和宏 ...

  10. java poi 操作word遇到的问题

    java poi 操作word文本,图表,遇到的问题 直接上问题 模板字段匹配问题 图表问题 图表导出 问题:模板找不到对应图表 问题:数据填充后效果不达目标 图表中为零的数值去掉(!!!模板层面解决 ...

最新文章

  1. 【带你重拾Redis】Redis 主从架构
  2. Emai乱码——解决的“迂回”战术
  3. 深入解读MySQL8.0 新特性 :Crash Safe DDL
  4. 程序员的4种心态与4种将来
  5. ToastUtil【简单的Toast封装类】【未自定义Toast的显示风格】
  6. html 并集选择器,CSS并集选择器
  7. css 控制图片最大宽度
  8. 《MPLS在Cisco IOS上的配置》一第 1 章 MPLS概述1.1 IP转发过程概述
  9. 微软发布 VS Code Jupyter 插件!不止 Python,多语言的 Jupyter Notebook支持来了!
  10. 关于python字符串format的一些花式用法
  11. SQL Server 2008文件与文件组的关系
  12. ACM程序设计大赛题目分类
  13. silvaco的石墨烯fet仿真_两米长的高功率因子石墨烯膜!散热发电两不误!
  14. 乌合之众-大众心理研究(五)
  15. Lexar雷克沙 nCARD存储卡全网发布,可用于华为手机内存扩容
  16. 【计算机毕业设计】java线上教学平台 springboot智慧教学系统
  17. 8、Oracle:group by用法
  18. 奇安信可信浏览器下载地址
  19. 重复读取输入流InputStream
  20. fluent二维叶型仿真_Hitalk—长沙理工大学机械软件仿真作品设计大赛

热门文章

  1. 应用的未来——面孔、豌豆荚、HTML5小组专家访谈
  2. 翻译文件名称,如何操作将中文名称翻译成英文名称
  3. 智能合约的投票、拍卖、远程购买、付款
  4. ERROR c.a.d.p.DruidDataSource - [init,905] - init datasource error, url: jdbc:mysql://xxx.xxx.xxx.xx
  5. php 根据多维数组中的某个值进行合并并且不删除数组
  6. 互联网掀起农家乐,巨头上演AI掘金战
  7. “苹果吃饱”的平板市场,新老玩家的翻盘之争
  8. IDEA熟能生巧大纲
  9. 猪宝宝:不到万不得已别当程序员
  10. mysql查询数据库所有表名字