使⽤POI将Word转HTML遇到的问题
近期做的⼀个功能,将Word转为HTML,因为这⼀块是盲点,所以代码借鉴了⽹上的某个⼤佬。
⼀、docx⽂件转HTML
1、乱码问题:读写⽂件时必须将编码格式统⼀“utf-8”。否则你会发现,单独打开⽂件时正常,⽤浏览器预览时就乱码了。从代码中仔细查,⼀定有某个地⽅没有设置编码格式。
2、docx⽂件相当于Word的压缩⽂件。使⽤压缩⼯具打开⽅式,可以看到⽂件中的xml⽂件。如图:
其中l⽂件就是docx⽂件的主⽂件,可以看出⽂件中的详细内容,如:⽂本、图⽚、公式以及样式。
3、转换代码:这⾥只获取⽂件中的⽂本内容(包括表格)、图⽚、公式。具体还有没有别的需求,还待测试,先做⼀个记录。
⽂本中如果有上下标,不会当作公式处理,必须⼿动转换。
VerticalAlign vertAlign = Subscript();
int sort = Value();
sort分别代表:1、BASELINE 指定⽗运⾏中的⽂本应位于基线处,并以与周围⽂本相同的⼤⼩显⽰。2、SUBSCRIPT 指定此⽂本应为上标。 3、SUPERSCRIPT 下标。
* 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 = BodyElements();
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 (!ists()) {
folder.mkdirs();
}
//构造ImageParse
ImageParse 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.String());
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 = Document();
NamedNodeMap shapeAttrs = Attributes();
// 图⽚在Word中显⽰的宽⾼
String style = NamedItem("style").getNodeValue();
NamedNodeMap imageAttrs = Attributes();
/
/ 图⽚在Word中的ID
String imageRid = NamedItem("r:id").getNodeValue();
// 获取图⽚信息
PackagePart imgPart = PartById(imageRid);
String imgUrl = PartName().getName();
String imgName = imgUrl.substring(imgUrl.lastIndexOf("/"),imgUrl.lastIndexOf("."));//图⽚名称
//保存公式图⽚
InputStream in = InputStream();
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格式图⽚转成svg
convertSVG(imgPath+"/"+imgName+".wmf");
imgName += ".svg";
NamedNodeMap binAttrs = Attributes();
// 公式⼆进制⽂件在Word中的ID
String binRid = NamedItem("r:id").getNodeValue();
/
/ 获取⼆进制⽂件
PackagePart binPart = PartById(binRid);
html document是什么//保存公式源⽂件,以供后续使⽤
File file=new File(imgPath.substring(0, imgPath.lastIndexOf("/image"))+"/math_source");
if(!ists()){//如果⽂件夹不存在
file.mkdir();//创建⽂件夹
}
InputStream inBin = InputStream();
FileOutputStream outBin = new FileOutputStream(new Path()+PartName().getName().PartName().getName().lastInde
FileOutputStream outBin = new FileOutputStream(new Path()+PartName().getName().PartName().getName().
byte[] bufferBin=new byte[2097152];
int readByteBin = 0;
while((readByte = ad(bufferBin)) != -1){
outBin.write(buffer, 0, readByteBin);
}
inBin.close();
outBin.close();
String relPath = placeFirst(CommonConstants.fileRoot, "");
math.append(" src=\""+relPath+imgName+"\"");
math.append(" style=\""+style+"\"/> ");
String();
}
/**
* 获取⼀个⼦标签对象
* @param node
* @param nodeName
* @return
*/
private static Node getChildNode(Node node, String nodeName) {
if (!node.hasChildNodes()) {
return null;
}
NodeList childNodes = ChildNodes();
for (int i = 0; i < Length(); i++) {
Node childNode = childNodes.item(i);
if (nodeName.NodeName())) {
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 = place(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 = Document();
OutputStream out = new FileOutputStream(dest);
if (dsWith(".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 = wInstance();
Transformer transformer = wTransformer();
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,
"/TR/2001/REC-SVG-20010904/DTD/svg10.dtd");
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 = de2XmlStr(node);
// encoding utf-16
String mathML = l2Xml(s, streamSource);
mathML = placeAll("xmlns:m=\"/officeDocument/2006/math\"", ""); mathML = placeAll("xmlns:mml", "xmlns");
mathML = placeAll("mml:", "");
return mathML;
}
/**
* MathML转PNG
* @param node
* @param imageParser
* @return
* @throws Exception
*/
public static String convertOmathToPng(XmlObject xmlObject, ImageParse imageParser) {
Document document = null;
try {
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论