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

2 篇文章 1 订阅

引言

思路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>

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

评论 22
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值