java使用poi读写word中的图片(二)
文章目录
- 准备工作
- 简单读取
- 复杂读取
- 查看Word的XML
- 特别说明:Word中的Svg图片
- 第一种写入图片到Word中的方式
- 第二种写入图片到Word中的方式
- 最后
准备工作
这里就不在复述了,可以看上一篇博文 java使用poi读写word中的内容(包含表格内容)(一)
代码中MyUnits工具类在我另一篇博文中 word中各种长度转换为px(工具类)
简单读取
如果后期还有回写到word中不建议使用这种方式读取。
@Test
public void test() throws FileNotFoundException, IOException {
XWPFDocument document = new XWPFDocument(new FileInputStream("D:\\Test\\word\\test1.docx"));
try {
List<XWPFParagraph> paragraphs = document.getParagraphs();
for (XWPFParagraph paragraph : paragraphs) {
List<XWPFRun> runs = paragraph.getRuns();
for (XWPFRun run : runs) {
List<XWPFPicture> pictures = run.getEmbeddedPictures();
// 我这里是偷懒,请使用循环
XWPFPicture picture = pictures.get(0);
XWPFPictureData pictureData = picture.getPictureData();
System.out.println(pictureData.getPictureType());
System.out.println(pictureData.getFileName());
System.out.println(pictureData.getData());
}
}
} finally {
document.close();
}
}
上面代码中,可以直接取出word中的图片,但是无法取出图片在word中的大小此处要注意,word中图片的大小可能与图片的大小不一致
操作word你就知道,图片放入word中后是可以放大或缩小的
复杂读取
@Test
public void test1() throws FileNotFoundException, IOException {
XWPFDocument document = new XWPFDocument(new FileInputStream("D:\\Test\\word\\test1.docx"));
try {
List<XWPFParagraph> paragraphs = document.getParagraphs();
for (XWPFParagraph paragraph : paragraphs) {
List<XWPFRun> runs = paragraph.getRuns();
for (XWPFRun run : runs) {
Node node = run.getCTR().getDomNode();
// drawing 一个绘画的图片
Node drawingNode = getChildNode(node, "w:drawing");
if (drawingNode == null) {
continue;
}
// 绘画图片的宽和高
Node extentNode = getChildNode(drawingNode, "wp:extent");
NamedNodeMap extentAttrs = extentNode.getAttributes();
System.out.println("宽:".concat(extentAttrs.getNamedItem("cx").getNodeValue()).concat("emu"));
System.out.println("高:".concat(extentAttrs.getNamedItem("cy").getNodeValue()).concat("emu"));
// 绘画图片具体引用
Node blipNode = getChildNode(drawingNode, "a:blip");
NamedNodeMap blipAttrs = blipNode.getAttributes();
String rid = blipAttrs.getNamedItem("r:embed").getNodeValue();
System.out.println("word中图片ID:".concat(rid));
// 获取图片信息
PackagePart part = document.getPartById(rid);
System.out.println(part.getContentType());
System.out.println(part.getPartName().getName());
System.out.println(part.getInputStream());
System.out.println("------ run ------");
}
System.out.println("------ paragraph ------");
}
} finally {
document.close();
}
}
private 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;
}
上面代码中既可以读取到图片在word中的宽高,也可以读取到图片的信息
注意宽和高的单位为emu
emu
转px
的工具类我已经共享出来了,word中各种长度转换为px(工具类)
查看Word的XML
w:drawing
、wp:extent
、a:blip
等等,这些我是怎么知道的呢?
当然是直接在word里面看见的了,下面教大家如何看word的xml
首先要安装压缩工具(我用的是360压缩)
选择用360压缩打开
打开后双击word文件夹
将document.xml拉倒桌面,然后将文件里的xml格式化一下就可以看到了,如图
特别说明:Word中的Svg图片
这里特别说明一下,如果将svg
(手动操作Word并非程序操作)图片插入word中的话,Word会生成一张png
图片。Word中显示的也是png
图片。这里我们看下xml
仔细看,这段xml
中有两处r:embed
第一处r:embed=”rId6″引用的是png
图片
第二处r:embed=”rId7″引用的才是你插入的svg
图片
<w:drawing>
<wp:inline distT="0" distB="0" distL="0" distR="0" wp14:anchorId="43206650" wp14:editId="4D01F649">
<wp:extent cx="352425" cy="200025"/>
<wp:effectExtent l="0" t="0" r="9525" b="9525"/>
<wp:docPr id="1" name="图形 1"/>
<wp:cNvGraphicFramePr>
<a:graphicFrameLocks xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" noChangeAspect="1"/>
</wp:cNvGraphicFramePr>
<a:graphic xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main">
<a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/picture">
<pic:pic xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture">
<pic:nvPicPr>
<pic:cNvPr id="1" name=""/>
<pic:cNvPicPr/>
</pic:nvPicPr>
<pic:blipFill>
<a:blip r:embed="rId6">
<a:extLst>
<a:ext uri="{96DAC541-7B7A-43D3-8B79-37D633B846F1}">
<asvg:svgBlip xmlns:asvg="http://schemas.microsoft.com/office/drawing/2016/SVG/main" r:embed="rId7"/>
</a:ext>
</a:extLst>
</a:blip>
<a:stretch>
<a:fillRect/>
</a:stretch>
</pic:blipFill>
<pic:spPr>
<a:xfrm>
<a:off x="0" y="0"/>
<a:ext cx="352425" cy="200025"/>
</a:xfrm>
<a:prstGeom prst="rect">
<a:avLst/>
</a:prstGeom>
</pic:spPr>
</pic:pic>
</a:graphicData>
</a:graphic>
</wp:inline>
</w:drawing>
第一种写入图片到Word中的方式
注意:
这种方式写入图片,宽高单位必须是emu
@Test
public void test2() throws IOException, InvalidFormatException {
XWPFDocument document = new XWPFDocument();
try {
XWPFParagraph paragraph = document.createParagraph();
XWPFRun run = paragraph.createRun();
InputStream is = new FileInputStream("D:\\Test\\word\\aa.png");
// 因为FileInputStream没有重写reset() 所有将流转为了byte数组
byte[] bs = IOUtils.toByteArray(is);
BufferedImage image = ImageIO.read(new ByteArrayInputStream(bs));
int width = MyUnits.pxToEMU(image.getWidth());
int height = MyUnits.pxToEMU(image.getHeight());
run.addPicture(new ByteArrayInputStream(bs), Document.PICTURE_TYPE_PNG, "", width, height);
OutputStream stream = new FileOutputStream("D:\\Test\\word\\w_test.docx");
document.write(stream);
} finally {
document.close();
}
}
看看写入的效果
第二种写入图片到Word中的方式
相对第一种这种方式要复杂一点
注意:
这种方式写入图片的宽高in
、mm
、cm
、pt
、px
都可以使用,我这里用的是pt
.
@Test
public void test3() throws IOException {
XWPFDocument document = new XWPFDocument();
try {
XWPFParagraph paragraph = document.createParagraph();
XWPFRun run = paragraph.createRun();
// 获取图片
InputStream is = new FileInputStream("D:\\Test\\word\\aa.png");
byte[] bs = IOUtils.toByteArray(is);
BufferedImage image = ImageIO.read(new ByteArrayInputStream(bs));
// 获取组装图片宽高,单位pt
StringBuffer dataSize = new StringBuffer();
dataSize.append("width:").append(MyUnits.pxToPt(image.getWidth())).append("pt;");
dataSize.append("height:").append(MyUnits.pxToPt(image.getHeight())).append("pt;");
// 添加图片到Word中
String rid = document.addPictureData(bs, Document.PICTURE_TYPE_PNG);
StringBuffer xml = new StringBuffer();
xml.append("<w:pict xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\"");
xml.append(" xmlns:v=\"urn:schemas-microsoft-com:vml\" xmlns:o=\"urn:schemas-microsoft-com:office:office\"");
xml.append(" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\">\r\n");
xml.append(" <v:shape id=\"图片1").append("\" o:spid=\"\" type=\"\" alt=\"\" style=\"").append(dataSize).append("\">\r\n");
xml.append(" <v:imagedata r:id=\"").append(rid).append("\" o:title=\"\" />");
xml.append(" </v:shape>\r\n");
xml.append("</w:pict>");
InputSource source = new InputSource(new StringReader(xml.toString()));
org.w3c.dom.Document pictDoc = DocumentHelper.readDocument(source);
// 将信息写入run中
run.setEmbossed(true);
XmlObject xmlObject = XmlObject.Factory.parse(pictDoc.getDocumentElement(), POIXMLTypeLoader.DEFAULT_XML_OPTIONS);
run.getCTR().set(xmlObject);
OutputStream stream = new FileOutputStream("D:\\Test\\word\\w_test1.docx");
document.write(stream);
} catch (Exception e) {
e.printStackTrace();
} finally {
document.close();
}
}
看看写入效果
最后
如果有什么不明白的可以留言。
欢迎大家留言讨论。
原文作者:圣诞节G
原文地址: https://blog.csdn.net/qq_18219457/article/details/98184621
本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
原文地址: https://blog.csdn.net/qq_18219457/article/details/98184621
本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
相关文章