(二)、JAVA基于OPENXML的word文档插入、合并、替换操作系列之基础篇-图片在word结构中的存放、插入、替换图片

(二)、JAVA基于OPENXML的word文档插入、合并、替换操作系列之基础篇-图片在word结构中的存放、插入图片

准备工作

在上一篇的《一个word文档的真实面目》中,我列出了一个word文档被解压后的全部结构,如果没看到的可以通过传送门了解一下。
本篇笔记的内容是后续word插入、替换、合并的基础,如果不考虑带图片的内容,请忽略本篇。

word中图片存放处理

先来看张word解压后与原图的对比, 相信你一眼就能看到media这个玩意儿,对,你猜的没错,word中的图片它最终会存储media目录下面,那word是怎么找它呢,这就是接下来的内容,让我来一层一层扒开它。
在这里插入图片描述
在上一篇中我提到了document.xml将是本系列的重点,那么现在就要从它开起拔起了,以下贴一段上面那个word的document.xml的片段(限于篇幅,这里就只放一段了)

<!-- 上面部分省略.... -->
<w:p>
   <w:pPr>
       <w:spacing w:after="450"/>
       <w:ind w:left="120"/>
       <w:jc w:val="center"/>
   </w:pPr>
   <w:r>
       <w:drawing>
           <wp:inline distT="0" distB="0" distL="0" distR="0">
               <wp:extent cx="8466666" cy="4496254"/>
               <wp:effectExtent l="0" t="0" r="0" b="0"/>
               <wp:docPr id="0" name="" descr=""/>
               <wp:cNvGraphicFramePr>
                   <a:graphicFrameLocks noChangeAspect="true"/>
               </wp:cNvGraphicFramePr>
               <a:graphic>
                   <a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/picture">
                       <pic:pic>
                           <pic:nvPicPr>
                               <pic:cNvPr id="1" name=""/>
                               <pic:cNvPicPr/>
                           </pic:nvPicPr>
                           <pic:blipFill>
                           		<!-- 这里定义资源ID引用 -->
                               <a:blip r:embed="rId5"/>
                               <a:stretch>
                                   <a:fillRect/>
                               </a:stretch>
                           </pic:blipFill>
                           <pic:spPr>
                               <a:xfrm>
                                   <a:off x="0" y="0"/>
                                   <a:ext cx="8466666" cy="4496254"/>
                               </a:xfrm>
                               <a:prstGeom prst="rect">
                                   <a:avLst/>
                               </a:prstGeom>
                           </pic:spPr>
                       </pic:pic>
                   </a:graphicData>
               </a:graphic>
           </wp:inline>
       </w:drawing>
   </w:r>
</w:p>
<!-- 下面部分省略.... -->

     不知道诸位有没有发现点什么(markdown的代码块中怎么加粗没找到办法,各位自己看吧),<w:drawing> 这个玩意在上一篇的《关于word文档WordprocessingML的表达方式》中提过,它就是用来在word中放图片的,这个标签里面又定义了许多的其他子标签,它们是用来定位这张图片的大小、位置、在word的布局等等信息的,在本篇中不作重点介绍,有兴趣的自行研究。
     那么问题来了,既然是放图片的, 那在这段代码中了没看到跟实际图片有关联的地方啊,它是怎么加载图片的呢,稍等莫急,我们重点来看一下这段 <a:blip r:embed="rId5"/> ,这个又是什么意思呢,先卖个关子,下面隆重介绍一下第二个重点要关注的文件document.xml.rels,在上面的图中我已经框出来了,没印象回过头再去看一下,打开它后是这样的:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
	<Relationship Id="rId1" Target="styles.xml" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles"/>
	<Relationship Id="rId2" Target="settings.xml" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings"/>
	<Relationship Id="rId3" Target="numbering.xml" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering"/>
	<Relationship Id="rId4" Target="media/document_image_rId4.png" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"/>
	<!-- 这里定义资源ID与具体资源位置的关联 -->
	<Relationship Id="rId5" Target="media/document_image_rId5.png" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"/>
</Relationships>

你们发现了什么? 别告诉我你看到了姑娘,我不信,除非你给我买包好烟,哈哈。
<a:blip r:embed="rId5"/>中引用的 r:embed值就是一个资源ID,而这个资源就是在 document.xml.rels中定义的,这里说的是资源,而不是图片,大家应该看到了文件中定义的除非了图片,还有其他的,自然不排除word中再嵌套其他文件啥的也是在这里面实现,当然我没有验证, 而本例的word中有两张图片,对应的资源ID分别为 rId4、rId5 这个ID是word在添加图片时自动生成的,而是递增的,会根据当前文件中已有资源数量增加,这个我验证过了。
总结一下就是,在你往word中插入一张图片时,首先它会将这张图片写入到media目录下,并同时生成一个资源ID, 然后会在 document.xml.rels中将这个ID与资源具体位置建立关联, 最后在document.xml中用<w:drawing> 来定义这张图片,并与资源ID绑定上,这样就能找到具体对应的图片了。

获取word中的所有图片

上面我们了解了图片在word中的挂载方式,接下来该是我们盘它的时候了,获取就不用说了。

	@Test
    public void testGetWordImage() throws InvalidFormatException, IOException {
        XWPFDocument  document = new XWPFDocument(OPCPackage.open("/Users/tenney/Desktop/2222222222.docx"));
        List<XWPFPictureData> allPictures = document.getAllPictures();

        System.err.println( "word中图片数据:" + allPictures.size());

        allPictures.forEach(p->{
        	//p.getData()  图片字节数组,可自行处理
            System.err.println(p.getFileName() + " : " + p.getPictureType() );  
        });
    }

在这里插入图片描述

往word中插入图片

不啰嗦了,直接上代码吧

	@Test
    public void testAppendWordImage() throws InvalidFormatException, IOException {
//        读入一个文档
        XWPFDocument  document = new XWPFDocument(OPCPackage.open("/Users/tenney/Desktop/2222222222.docx"));
        FileInputStream fis = new FileInputStream("/Users/tenney/Desktop/test.jpg");

        //创建一个段落,把图片放到这个段落里面
        XWPFParagraph title = document.createParagraph();
        XWPFRun run = title.createRun();
        run.setText("图片名称");
        run.setBold(true);
        title.setAlignment(ParagraphAlignment.CENTER);

        //添加图片
        //该方法会向word中写入图片,并返回资源关系ID,即r:embed值,但打开文档不会显示,因为它未在document.xml文件中画出来
//        document.addPictureData(IOUtils.toByteArray(fis), org.apache.poi.xwpf.usermodel.Document.PICTURE_TYPE_JPEG);
        run.addBreak();
        run.addPicture(fis, XWPFDocument.PICTURE_TYPE_JPEG, "test.jpg", Units.toEMU(300), Units.toEMU(200)); // 300x200 pixels

        //将文档重新保存
        FileOutputStream fos = new FileOutputStream("/Users/tenney/Desktop/image.docx");
        document.write(fos);
        fos.close();
    }

执行效果如下:
在这里插入图片描述

替换word中的图片

这部分交给你们了,不接收反驳,哈哈

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值