java 转 docx 生成 html 含图片,word公式,wps公式,自动编号,表格

引言

思路word中的docx是 Office Open XML 标准的文档格式,所以可以通过apache 的poi解析,docx的文档组件在poi中的结构是这样的

word文档 的组件 poi中的对象
word文件 XWPFDocument
段落 XWPFParagraph
表格 XWPFTable
自动编号 XWPFParagraph.getNumFmt()
段落中的小单元,可以是一个图片或文字或公式 文本是XWPFRun,图片是XWPFPicture,公式是CTOMath

第一步处理自动编号和XWPFRun与CTOMath的顺序问题

public static String parseDocxContentToHTML(InputStream input, ImageParse imageParser) throws IOException {
    
    
        if (input == null) {
    
    
            throw new RuntimeException("请输入要转的docx的文件");
        }
        StringBuilder content = new StringBuilder();
        Map<BigInteger, IWordNumber> wordNumberMap = new HashMap<BigInteger, IWordNumber>();
        XWPFDocument docx = new XWPFDocument(input);
        // 拿到所有的段落的表格,这两个属于同级无素
        List<IBodyElement> elements = docx.getBodyElements();
        for (IBodyElement body : elements) {
    
    
            if (body.getElementType().equals(BodyElementType.PARAGRAPH)) {
    
    
                handleParagraph(content, body, wordNumberMap, imageParser);
            } else if (body.getElementType().equals(BodyElementType.TABLE)) {
    
    
                handleTable(content, body, wordNumberMap, imageParser);
            }
        }
        return content.toString();
    }

第二步,分别处理段和表格

  private static void handleParagraph(StringBuilder content, IBodyElement body, Map<BigInteger, IWordNumber> wordNumberMap, ImageParse imageParser) {
    
    
      XWPFParagraph p = (XWPFParagraph) body;
      if (p.isEmpty() || p.isWordWrap() || p.isPageBreak()) {
    
    
          return;
      }
      String tagName = "p";
      content.append("<" + tagName + ">");
      // 自动编号
      handleWordNumber(content, wordNumberMap, p);
      /*XWPFParagraph 有两个方法可以分别提出XWPFRun和CTOMath,但是不知道位置
      ParagraphChildOrderManager这个类是专门解决这个问题的
      */
      ParagraphChildOrderManager runOrMaths = new ParagraphChildOrderManager(p);
      List<Object> childList = runOrMaths.getChildList();
      for (Object child : childList) {
    
    
          if (child instanceof XWPFRun) {
    
    
              handleParagraphRun(content, (XWPFRun) child, imageParser);
          } else if (child instanceof CTOMath) {
    
    
              handleParagraphOMath(content, (CTOMath) child, imageParser);
          }
      }
      content.append("</" + tagName + ">");
  }
//可以把公式和XWPFRun按顺序遍历,用到了以CTP开头的底层方式,中间也参观了别的人实现,自己改造
public class ParagraphChildOrderManager {
    
    
  public static int TYPE_RUN = 1;
  public static int TYPE_OMATH = 2;

  List<Integer> typeList = new ArrayList<>();
  XWPFParagraph p;

  public ParagraphChildOrderManager(XWPFParagraph paragraph) {
    
    
      this.p = paragraph;
      List<CTOMathPara> oMathParaList = paragraph.getCTP().getOMathParaList();
      //using a cursor to go through the paragraph from top to down
      XmlCursor xmlcursor = paragraph.getCTP().newCursor();
      while (xmlcursor.hasNextToken()) {
    
    
          XmlCursor.TokenType tokenType = xmlcursor.toNextToken();
          if (tokenType.isStart()) {
    
    
              if (xmlcursor.getName().getPrefix().equalsIgnoreCase("w") && xmlcursor.getName().getLocalPart().equalsIgnoreCase("r")) {
    
    
                  typeList.add(TYPE_RUN);
              } else if (xmlcursor.getName().getLocalPart().equalsIgnoreCase("oMath")) {
    
    
                  typeList.add(TYPE_OMATH);
              }
          } else if (tokenType.isEnd()) {
    
    
              xmlcursor.push();
              xmlcursor.toParent();
              if (xmlcursor.getName().getLocalPart().equalsIgnoreCase("p")) {
    
    
                  break;
              }
              xmlcursor.pop();
          }
      }
  }

  public List<Object> getChildList() {
    
    
      List<Object> runsOrMathList = new ArrayList<>();
      List<XWPFRun> runs = p.getRuns();
      List<CTOMath> oMathList = p.getCTP().getOMathList();
      int totalRuns = runs.size() + oMathList.size();
      if (typeList.size() != totalRuns) {
    
    
          throw new RuntimeException(" word 文件解析公式有问题,请与管理员联系");
      }
      Queue<XWPFRun> runsQueue = new LinkedList<>(runs);
      Queue<CTOMath> mathQueue = new LinkedList<>(oMathList);
      for (int i = 0; i < typeList.size(); i++) {
    
    
          Integer type = typeList.get(i);
          if (type.equals(TYPE_RUN) && runs.size() > 0) {
    
    
              runsOrMathList.add(runsQueue.poll());
          } else if (type.equals(TYPE_OMATH) && mathQueue.size() > 0) {
    
    
              runsOrMathList.add(mathQueue.poll());
          }
      }
      return runsOrMathList;
  }
}
// 处理自动编号的代码如下
private static void handleWordNumber(StringBuilder sb, Map<BigInteger, IWordNumber> wordNumberMap, XWPFParagraph p) {
    
    
      String prefix = null;
      if (wordNumberMap != null && p.getNumID() != null && p.getNumFmt() != null) {
    
    
          IWordNumber wn = wordNumberMap.get(p.getNumID());
          if (wn != null) {
    
    
              prefix = wn.nextNum();
          } else {
    
    
              IWordNumber newWordNumber = WordNumberFactory.getWordNumber(p.getNumFmt(), p.getNumLevelText());
              if (newWordNumber != null) {
    
    
                  wordNumberMap.put(p.getNumID(), newWordNumber);
                  prefix = newWordNumber.nextNum();
              }
          }
      }
      if (StringUtils.isNotBlank(prefix)) {
    
    
          sb.append(prefix);
      }
  }
// 这里贴了数字和自动编号的实现,虽的类似,我就不贴了
public class WordNumberFactory {
    
    
  public static IWordNumber getWordNumber(String numFmt, String numLevelText) {
    
    
      if ("decimal".equals(numFmt)) {
    
    
          return new DecimalNumber(numLevelText);
      } else if ("upperLetter".equals(numFmt)) {
    
    
          return new UpperLetterNumber(numLevelText);
      } else if ("japaneseCounting".equals(numFmt)) {
    
    
          return new JapaneseCountingNumber(numLevelText);
      }
      return null;
  }
}

public class DecimalNumber extends BaseNumber implements IWordNumber {
    
    
  int number = 0;

  public DecimalNumber(String splitChar) {
    
    
      super(splitChar);
  }

  @Override
  public String nextNum() {
    
    
      number++;
      return number + this.splitChar;
  }
}

public class UpperLetterNumber extends BaseNumber implements IWordNumber {
    
    
  char number = 'A';

  public UpperLetterNumber(String splitChar) {
    
    
      super(splitChar);
  }


  @Override
  public String nextNum() {
    
    
      String value = number + this.splitChar;
      number++;
      return value;
  }
}

public class JapaneseCountingNumber extends BaseNumber implements IWordNumber {
    
    
  String[] baseWord = {
    
    "十", "一", "二", "三", "四", "五", "六", "七", "八", "九"};
  String dot = "、";
  int count = 0;

  public JapaneseCountingNumber(String splitChar) {
    
    
      super(splitChar);
  }

  @Override
  public String nextNum() {
    
    
      count++;
      int unit = 0;
      if (count > 99) {
    
    
          throw new RuntimeException("仅支持100以下的自动编码");
      }
      if (count > 19) {
    
    
          int ten = count / 10;
          unit = count % 10;
          if (unit == 0) {
    
    
              return baseWord[ten] + "十" + dot;
          } else {
    
    
              return baseWord[ten] + "十" + baseWord[unit] + dot;
          }
      }
      if (count > 10) {
    
    
          unit = count % 10;
          return "十" + baseWord[unit] + dot;
      }
      unit = count % 10;
      return baseWord[unit] + dot;
  }
}

public class BaseNumber {
    
    
  BigInteger numberId;
  String fmt;
  String splitChar = ".";
  public BaseNumber(String splitChar) {
    
    
      if (splitChar.startsWith("%1")) {
    
    
          this.splitChar = splitChar.replace("%1", "");
      }
  }

  @Override
  public boolean equals(Object obj) {
    
    
      if (obj == null || this.getClass() != obj.getClass()) return false;
      BaseNumber bn = (BaseNumber) obj;
      if (bn.numberId == null || this.numberId == null) return false;
      if (bn.numberId == this.numberId) {
    
    
          return true;
      }
      return false;
  }

  @Override
  public int hashCode() {
    
    
      return numberId == null ? 0 : numberId.hashCode();
  }

}
public interface IWordNumber {
    
    
  public String nextNum();
}

// 结束处理自动编号

### 处理XWPFRun
private static void handleParagraphRun(StringBuilder content, XWPFRun run, ImageParse imageParser) {
    
    
//char[] runChars = run.toString().toCharArray();
      // 有内嵌的图片
      List<XWPFPicture> pics = run.getEmbeddedPictures();
      if (pics != null && pics.size() > 0) {
    
    
          handleParagraphRunsImage(content, pics, imageParser);
      } else if (isMath(run)) {
    
    // 处理wps的公式图片
          handleParagraphRunsImageMath(content, run, imageParser);
      } else {
    
     //处理文本
          handleParagraphRunsWithText(content, run);
      }
}
// 处理图片
private static void handleParagraphRunsImage(StringBuilder content, List<XWPFPicture> pics, ImageParse imageParser) {
    
    
      for (XWPFPicture pic : pics) {
    
    
          String desc = pic.getDescription();

          String path = imageParser.parse(pic.getPictureData().getData(),
                  pic.getPictureData().getFileName());
          log.debug("pic.getPictureData().getFileName()===" + pic.getPictureData().getFileName());

          CTPicture ctPicture = pic.getCTPicture();
          Node domNode = ctPicture.getDomNode();

          Node extNode = getChildChainNode(domNode, "pic:spPr", "a:ext");
          NamedNodeMap attributes = extNode.getAttributes();
          if (attributes != null && attributes.getNamedItem("cx") != null) {
    
    
              int width = WordMyUnits.emuToPx(new Double(attributes.getNamedItem("cx").getNodeValue()));
              int height = WordMyUnits.emuToPx(new Double(attributes.getNamedItem("cy").getNodeValue()));
              content.append(String.format("<img src=\"%s\" width=\"%d\" height=\"%d\" />", path, width, height));
          } else {
    
    
              content.append(String.format("<img src=\"%s\" />", path));
          }
      }
  }      
// 处理wps的内嵌的图片公式,里面有wmf to svg的工具类
private static boolean isMath(XWPFRun run) {
    
    
      Node runNode = run.getCTR().getDomNode();
      Node objectNode = getChildNode(runNode, "w:object");
      if (objectNode == null) {
    
    
          return false;
      }
      Node shapeNode = getChildNode(objectNode, "v:shape");
      if (shapeNode == null) {
    
    
          return false;
      }
      Node imageNode = getChildNode(shapeNode, "v:imagedata");
      if (imageNode == null) {
    
    
          return false;
      }
      Node binNode = getChildNode(objectNode, "o:OLEObject");
      if (binNode == null) {
    
    
          return false;
      }
      return true;
  }

  private static void handleParagraphRunsImageMath(StringBuilder content, XWPFRun run, ImageParse imageParser) {
    
    
      Node runNode = run.getCTR().getDomNode();
      XWPFDocument runDocument = run.getDocument();
      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;
      }
      NamedNodeMap shapeAttrs = shapeNode.getAttributes();
      // 图片在Word中显示的宽高
      String style = shapeAttrs.getNamedItem("style").getNodeValue();

      NamedNodeMap imageAttrs = imageNode.getAttributes();
      // 图片在Word中的ID
      String imageRid = imageAttrs.getNamedItem("r:id").getNodeValue();
      // 获取图片信息
      PackagePart imgPart = runDocument.getPartById(imageRid);
      // word/media/image4.wmf
      String fullName = imgPart.getPartName().getName();
      log.debug("pic.Match.fullName==" + fullName);
      String extName = imgPart.getPartName().getExtension();
      Pattern p = Pattern.compile("\\w+\\." + extName);
      Matcher matcher = p.matcher(fullName);
      if (matcher.find()) {
    
    
          fullName = matcher.group(0);
      }
      log.debug("pic.Match.name==" + fullName);
      try {
    
    
          ByteArrayOutputStream out = new ByteArrayOutputStream();
          WmfUtils.toSvg(imgPart.getInputStream(), out);
          fullName = fullName.replace(extName, "svg");
          String path = imageParser.parse(new ByteArrayInputStream(out.toByteArray()), fullName);
          content.append("<img src=\"" + path + "\" style=\"" + style + "\"/>");
      } catch (IOException e) {
    
    
          e.printStackTrace();
      }
  }
// 处理文本的html样式

private static void handleParagraphRunsWithText(StringBuilder content, XWPFRun run) {
    
    
      String c = run.toString();
      c = escapeHtmlTag(c);
      if (c == null || c.length() == 0) {
    
    
          return;
      }
      if (run.getSubscript() != null) {
    
    
          VerticalAlign va = run.getSubscript();
          if (va.equals(VerticalAlign.SUBSCRIPT)) {
    
    
              c = "<sub>" + c + "</sub>";
          } else if (va.equals(VerticalAlign.SUPERSCRIPT)) {
    
    
              c = "<sup>" + c + "</sup>";
          }
      }
      if (run.isBold()) {
    
    
          c = "<b>" + c + "</b>";
      } else if (run.isItalic()) {
    
    
          c = "<i>" + c + "</i>";
      } else if (run.isStrikeThrough()) {
    
    
          c = "<strike>" + c + "</strike>";
      }
      if (run.getUnderline() != null && run.getUnderline() != UnderlinePatterns.NONE) {
    
    
          c = "<span style='text-decoration: underline;'>" + c + "</span>";
      }
      if (run.getColor() != null) {
    
    
          c = "<span style='color:#" + run.getColor().toLowerCase() + ";'>" + c + "</span>";
      }
      content.append(c);
  }

private static String escapeHtmlTag(String text) {
    
    
      text = text.replace("&", "&amp;");
      text = text.replace("<", "&lt;");
      text = text.replace(">", "&gt;");
      return text;
  }

段处理完,该公式了 CTOMath,该公式是微软自己的公式

private static void handleParagraphOMath(StringBuilder content, CTOMath child, ImageParse imageParser) {
    
    
        String s = OmmlUtils.convertOmathToPng(child, imageParser);
        content.append(s);
    }
// omml先转成node,再转成string ,再转成mathML的string,再用第三工具生成图片
public class OmmlUtils {
    
    
    /**
     * 直接转node有等号会出问题,先转成xml的string,再转成mathML的字符串
     *
     * @param node
     * @return
     * @throws IOException
     * @throws TransformerException
     */
    private static String getMathMLFromNode(Node node) throws IOException, TransformerException {
    
    
        final String xslFile = "/OMML2MML.XSL";
        StreamSource streamSource = new StreamSource(OmmlUtils.class.getResourceAsStream(xslFile));
        String s = W3cNodeUtil.node2XmlStr(node);
        // encoding utf-16
        String 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;
    }


    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 (IOException e) {
    
    
            e.printStackTrace();
        } catch (TransformerException e) {
    
    
            e.printStackTrace();
        }
        return null;
    }

    private static String documentToImageHTML(Document document, ImageParse imageParser) {
    
    
        try {
    
    
            Converter mathMLConvert = Converter.getInstance();
            LayoutContextImpl localLayoutContextImpl = new LayoutContextImpl(LayoutContextImpl.getDefaultLayoutContext());
            localLayoutContextImpl.setParameter(Parameter.MATHSIZE, 18);
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            mathMLConvert.convert(document, os, "image/png", localLayoutContextImpl);
            String pngName = imageParser.parse(os.toByteArray(), ".png");
            os.close();
            return "<img src=\"" + pngName + "\" align=\"absmiddle\"/>";
        } catch (IOException e) {
    
    
            e.printStackTrace();
        } catch (Exception e) {
    
    
            e.printStackTrace();
        }
        return null;
    }
}

public class W3cNodeUtil {
    
    
    public static String node2XmlStr(Node node) {
    
    
        Transformer transformer = null;
        if (node == null) {
    
    
            throw new IllegalArgumentException("node 不能为空..");
        }
        try {
    
    
            transformer = TransformerFactory.newInstance().newTransformer();
        } catch (Exception e) {
    
    
            throw new RuntimeException(e.getMessage());
        }
        if (transformer != null) {
    
    
            try {
    
    
                StringWriter sw = new StringWriter();
                transformer.transform(new DOMSource(node), new StreamResult(sw));
                return sw.toString();
            } catch (TransformerException te) {
    
    
                throw new RuntimeException(te.getMessage());
            }
        }
        return null;
    }


    public static String xml2Xml(String xml, Source XSLSource) {
    
    
        Transformer transformer = null;
        if (xml == null) {
    
    
            throw new IllegalArgumentException("node 不能为空..");
        }
        try {
    
    
            if (XSLSource == null) {
    
    
                transformer = TransformerFactory.newInstance().newTransformer();
            } else {
    
    
                transformer = TransformerFactory.newInstance().newTransformer(XSLSource);
            }
        } catch (Exception e) {
    
    
            throw new RuntimeException(e.getMessage());
        }
        if (transformer != null) {
    
    
            try {
    
    
                Source source = new StreamSource(new StringReader(xml));
                StringWriter sw = new StringWriter();
                transformer.transform(source, new StreamResult(sw));
                return sw.toString();
            } catch (TransformerException te) {
    
    
                throw new RuntimeException(te.getMessage());
            }
        }
        return null;
    }

    public static Document xmlStr2Node(String xmlString, String encoding) {
    
    
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        Document doc = null;
        try {
    
    
            InputStream is = new ByteArrayInputStream(xmlString.getBytes(encoding));
            doc = dbf.newDocumentBuilder().parse(is);
            is.close();
        } catch (Exception e) {
    
    
            e.printStackTrace();
        }
        return doc;
    }

    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;
    }

    public static Node getChildChainNode(Node node, String... nodeName) {
    
    
        Node childNode = node;
        for (int i = 0; i < nodeName.length; i++) {
    
    
            String tmp = nodeName[i];
            childNode = getChildNode(childNode, tmp);
            if (childNode == null) {
    
    
                return null;
            }
        }
        return childNode;
    }
}
public class WordMyUnits {
    
    
    public static final int EMU_PER_PX = 9525;
    public static final int emuToPx(double emu) {
    
    
        return (int) (emu/9525);
    }

}

处理表格,表格就容易多了,

// 处理table
    private static String handleTable(StringBuilder content, IBodyElement body, Map<BigInteger, IWordNumber> wordNumberMap, ImageParse imageParser) {
    
    
        XWPFTable table = (XWPFTable) body;
        List<XWPFTableRow> rows = table.getRows();
        content.append("<table class=\"paper-table\">");
        for (XWPFTableRow row : rows) {
    
    
            content.append("<tr>");
            List<XWPFTableCell> cells = row.getTableCells();
            for (XWPFTableCell cell : cells) {
    
    
                content.append("<td>");
                List<XWPFParagraph> paragraphs = cell.getParagraphs();
                for (XWPFParagraph paragraph : paragraphs) {
    
    
                    handleParagraph(content, paragraph, wordNumberMap, imageParser);
                }
                content.append("</td>\n");
            }
            content.append("</tr>\n");
        }
        content.append("</table>\n");
        return null;
    }
 // 还有一个保存图片到硬盘上的类
 public class ImageParse {
    
    
    int number = 0;
    private String targetDir;
    private String baseUrl;

    public ImageParse(String targetDir, String baseUrl) {
    
    
        super();
        this.targetDir = targetDir;
        this.baseUrl = baseUrl;
    }

    public String parse(byte[] data, String extName) {
    
    
        return parse(new ByteArrayInputStream(data), extName);
    }

    public String parse(InputStream in, String extName) {
    
    
        if (extName.lastIndexOf(".") > -1) {
    
    
            extName = extName.substring(extName.lastIndexOf(".") + 1);
        }
        String filename = "image_" + (number++) + "." + extName;
        File target = new File(targetDir);
        if (!target.exists()) {
    
    
            target.mkdirs();
        }
        try {
    
    
            IOUtils.copy(in, new FileOutputStream(new File(target, filename)));
        } catch (IOException e) {
    
    
            e.printStackTrace();
        }
        return baseUrl + filename;
    }
}


public class WmfUtils {
    
    
    public static void main(String[] args) {
    
    
        String result = convert("D:\\06training\\docx\\image1.wmf");
        System.out.println(result);
    }


    @Deprecated
    public static String convert2(String path) throws TranscoderException,
            IOException {
    
    
        String wmfPath = path;
        File wmf = new File(wmfPath);
        FileInputStream wmfStream = new FileInputStream(wmf);
        ByteArrayOutputStream imageOut = new ByteArrayOutputStream();
        int noOfByteRead = 0;
        while ((noOfByteRead = wmfStream.read()) != -1) {
    
    
            imageOut.write(noOfByteRead);
        }
        imageOut.flush();
        wmfStream.close();
        // wmf 转换为svg
        WMFTranscoder transcoder = new WMFTranscoder();
        // TranscodingHints hints = new TranscodingHints();
        // hints.put(WMFTranscoder.KEY_HEIGHT, 1000f);
        // hints.put(WMFTranscoder.KEY_WIDTH, 1500f);
        // transcoder.setTranscodingHints(hints);
        TranscoderInput input = new TranscoderInput(new ByteArrayInputStream(
                imageOut.toByteArray()));
        ByteArrayOutputStream svg = new ByteArrayOutputStream();
        TranscoderOutput output = new TranscoderOutput(svg);
        transcoder.transcode(input, output);
        String svgFile = FileExtNameUtils.replace(wmfPath, "wmf", "svg");
        FileOutputStream fileOut = new FileOutputStream(svgFile);
        fileOut.write(svg.toByteArray());
        fileOut.flush();
        fileOut.close();
        svg.close();
        // svg -> jpg
        ImageTranscoder it = new JPEGTranscoder();
        it.addTranscodingHint(JPEGTranscoder.KEY_QUALITY, 0.5);
        ByteArrayOutputStream jpg = new ByteArrayOutputStream();
        it.transcode(new TranscoderInput(new ByteArrayInputStream(svg
                .toByteArray())), new TranscoderOutput(jpg));
        String jpgFile = FileExtNameUtils.replace(wmfPath, "wmf", "jpg");
        FileOutputStream jpgOut = new FileOutputStream(jpgFile);
        jpgOut.write(jpg.toByteArray());
        jpgOut.flush();
        jpgOut.close();
        jpg.close();
        // Filor.deleteFile(svgFile);// 删除掉中间文件
        return jpgFile;
    }

    public static String convert(String path) {
    
    
        try {
    
    
            String svgFile = FileExtNameUtils.replace(path, "wmf", "svg");
            wmfToSvg(path, svgFile);
            String jpgFile = FileExtNameUtils.replace(path, "wmf", "png");
            svgToJpg(svgFile, jpgFile);
            return jpgFile;
        } catch (Exception e) {
    
    
            e.printStackTrace();
        }
        return null;

    }

    /**
     * 将svg转化为JPG
     *
     * @param src
     * @param dest
     */
    public static String svgToJpg(String src, String dest) {
    
    
        FileOutputStream jpgOut = null;
        FileInputStream svgStream = null;
        ByteArrayOutputStream svgOut = null;
        ByteArrayInputStream svgInputStream = null;
        ByteArrayOutputStream jpg = null;
        try {
    
    
            // 获取到svg文件
            File svg = new File(src);
            svgStream = new FileInputStream(svg);
            svgOut = new ByteArrayOutputStream();
            // 获取到svg的stream
            int noOfByteRead = 0;
            while ((noOfByteRead = svgStream.read()) != -1) {
    
    
                svgOut.write(noOfByteRead);
            }
            JPEGTranscoder it = new JPEGTranscoder();
            it.addTranscodingHint(JPEGTranscoder.KEY_QUALITY, (float) 1);
            it.addTranscodingHint(ImageTranscoder.KEY_WIDTH, 200f);
            jpg = new ByteArrayOutputStream();
            svgInputStream = new ByteArrayInputStream(svgOut.toByteArray());
            it.transcode(new TranscoderInput(svgInputStream),
                    new TranscoderOutput(jpg));
            jpgOut = new FileOutputStream(dest);
            jpgOut.write(jpg.toByteArray());
        } catch (Exception e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            try {
    
    
                if (svgInputStream != null) {
    
    
                    svgInputStream.close();
                }
                if (jpg != null) {
    
    
                    jpg.close();
                }
                if (svgStream != null) {
    
    
                    svgStream.close();
                }
                if (svgOut != null) {
    
    
                    svgOut.close();
                }
                if (jpgOut != null) {
    
    
                    jpgOut.flush();
                    jpgOut.close();
                }
            } catch (IOException e) {
    
    
                e.printStackTrace();
            }
        }
        return dest;
    }

    public static void toSvg(InputStream in, OutputStream out) {
    
    
        try {
    
    
            WmfParser parser = new WmfParser();
            final SvgGdi gdi = new SvgGdi(false);
            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();
        }
    }


    /**
     * 将wmf转换为svg
     *
     * @param src
     * @param dest
     */
    public static void wmfToSvg(String src, String dest) {
    
    
        InputStream in = null;
        OutputStream out = null;
        try {
    
    
            in = new FileInputStream(src);
            out = new FileOutputStream(dest);

        } catch (FileNotFoundException e) {
    
    
            e.printStackTrace();
        }
        toSvg(in, out);
    }

    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();
    }
}
public class FileExtNameUtils {
    
    
    public static String replace(String wmfPath, String wmf, String jpg) {
    
    
        int index = wmfPath.lastIndexOf("wmf");
        if (index > -1) {
    
    
            return wmfPath.substring(0, index) + jpg + wmfPath.substring(index + 3);
        }
        return wmfPath;
    }
}

用到的jar包

<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-ooxml-schemas</artifactId>
            <version>3.17</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>ooxml-schemas</artifactId>
            <version>1.3</version>
        </dependency>
        <dependency>
            <groupId>net.arnx</groupId>
            <artifactId>wmf2svg</artifactId>
            <version>0.9.8</version>
        </dependency>
        <dependency>
            <groupId>org.apache.xmlgraphics</groupId>
            <artifactId>batik-codec</artifactId>
            <version>1.7</version>
        </dependency>
        <dependency>
            <groupId>net.sourceforge.jeuclid</groupId>
            <artifactId>jeuclid-core</artifactId>
            <version>3.1.9</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.9</version>
        </dependency>

中间也参观了好多网站,就不一一列出来了,当时找的也是晕头转向的,最后整理也是相当费时间

猜你喜欢

转载自blog.csdn.net/redlevin/article/details/107153887