背景
最近遇到了一个从word文档中读取内容并回显的场景,具体要求就是从用户上传的word文档中读取到图片和文字内容,将图片保存到存储上之后,图文内容再回显到前端页面上。研究了一下Apache POI,实现流程还是比较简单的。
输入输出说明
1. 测试的Word文件如下图所示
2. 解析后回显的内容主体如下:
<p align='center'><img src='./data/output/7bd0cdfa-0284-4ddc-83da-e2d976fe4d4b.jpeg'/></p>
<p>12月4日,内地奥运健儿代表团成员苏炳添(右一)向观众挥手致意。新华社发</p>
<p> 光明日报记者 訾谦 陈芃朴</p>
<p> 香江之畔,狮子山下,内地奥运健儿访港代表团受到香港市民的热烈欢迎。短暂的三天时间里,香港街头处处弥漫着火一样的热情。活动现场,观众与奥运健儿亲切互动;会场之外,男女老少争相走上街头,希望一睹奥运健儿的英姿风采。</p>
<p> “其实香港对我来说是很熟悉的地方,因为我是看着香港的TVB电视剧长大的。”谈到对香港的印象,代表团成员、田径运动员苏炳添用粤语流利地对香港记者说。</p>
<p align='center'><img src='./data/output/eb2051b4-2a17-4dfd-8453-6d204e224707.jpeg'/></p>
<p>12月5日,内地奥运健儿代表团成员邹敬园(前左四)与参加活动的香港市民合影。新华社发 </p>
<p> 和苏炳添一样,三天的访港过程中,内地的奥运健儿们不仅是赛场上闪耀光芒的体育明星,还是生活中亲切可爱的“小哥哥”“小姐姐”。他们的纯真、活泼,让香港市民看到了新一代杰出运动员最真实的一面。</p>
<p> 在东京奥运会赛场上,国家队和中国香港队的健儿们不负众望,均取得了骄人成绩,令包括香港同胞在内的全国人民倍感自豪。比赛期间,国旗区旗一同升起、国家乒乓球队与中国香港乒乓球队合影的动人场景,在三天的活动中被反复提及。</p>
<p> “我们通过共同的努力,最后能够站在领奖台上,同国旗和区旗一起合影,是非常暖心的。”代表团成员、乒乓球奥运冠军马龙说,这一幕能够被内地和香港同胞津津乐道,证明了两地同胞深厚的情谊。每当屏幕上播放运动员在奥运会赛场上的精彩表现,总会收获现场震天的欢呼喝彩,不少观众激动得眼眶通红,流下热泪。</p>
<p align='center'><img src='./data/output/419e33ed-6596-48fc-a049-eee041deaacb.jpeg'/></p>
<p>12月4日,内地奥运健儿代表团游览维多利亚港,代表团成员在游船上自拍合影。新华社发</p>
<p> “我时隔9年再次来到香港,这9年间有很多辛酸,但为了实现梦想,一直奋斗。”这是举重奥运冠军吕小军的奋斗历程;</p>
<p> “人生最精彩的不是实现梦想的瞬间,而是追求梦想的过程。”这是自行车奥运冠军钟天使的人生格言;</p>
<p> “我们每个运动员能在赛场上发挥技术,不是全靠自己,还需要国家作为后盾支持我们。”这是体操奥运冠军邹敬园的深切感悟;</p>
<p> …………</p>
<p align='center'><img src='./data/output/2ee655a8-68d8-4541-a5b6-1a9c4ad89c6b.jpeg'/></p>
<p>12月4日,内地奥运健儿在伊利沙伯体育馆进行表演活动,图为奥运健儿入场。新华社发</p>
<p> 此次内地奥运健儿访港,带来的不仅是高难度的竞赛技巧,更是那份为国争光的荣耀、顽强拼搏的斗志和追求梦想的坚持,是令人难以忘怀的正能量。</p>
<p> 同胞情深,暖意浓浓。送别内地奥运健儿,依依不舍的情绪萦绕在香港的大街小巷。奥运健儿乘坐大巴经过时,总能看到面带笑容挥手道别的香港市民。相信在未来,奥运健儿追逐梦想的感人故事将与狮子山下精神相互激荡,始终激励香港同胞与内地同胞更紧密地团结起来,一同为中华民族伟大复兴的中国梦而奋斗!</p>
<p align='center'><img src='./data/output/41a0595a-6793-46ef-97c2-005c7174f32b.jpeg'/></p>
<p>12月5日,内地奥运健儿代表团成员汪周雨与香港小朋友互动。新华社发</p>
<p> 《光明日报》( 2021年12月07日 07版)</p>
处理过程
1. 引入 Apache POI 依赖
<properties>
<!-- other properties -->
<poi.version>5.1.0</poi.version>
<!-- other properties -->
</properties>
<dependencies>
<!-- other dependencies -->
<!-- Apache POI Dependency -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>${poi.version}</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>${poi.ooxml.version}</version>
</dependency>
<!-- other dependencies -->
</dependencies>
2. 解析docx内容的Java代码
@Test
public void testParseDocx() throws IOException {
try (XWPFDocument document = new XWPFDocument(new FileInputStream("./data/input/图文测试样本.docx"))) {
List<XWPFParagraph> paragraphs = document.getParagraphs();
StringBuffer currArticle = new StringBuffer();
paragraphs.forEach(paragraph -> {
List<XWPFRun> runs = paragraph.getRuns();
String paragraphText = paragraph.getParagraphText();
if (StringUtils.hasText(paragraphText)) {
// 文字段落
currArticle.append("<p>").append(paragraphText).append("</p>").append(System.lineSeparator());
} else {
// 图片段落
for (XWPFRun run : runs) {
List<XWPFPicture> pictures = run.getEmbeddedPictures();
// TODO 先假设一段只有一张图片
XWPFPicture picture = pictures.get(0);
XWPFPictureData pictureData = picture.getPictureData();
String imageNameOld = pictureData.getFileName();
String imageType = imageNameOld.substring(imageNameOld.lastIndexOf(".") + 1);
String imageNameNew = UUID.randomUUID() + "." + imageType;
String imagePath = "./data/output/" + imageNameNew;
try {
ImageIO.write(ImageIO.read(new ByteArrayInputStream(pictureData.getData())), imageType, new File(imagePath));
} catch (IOException e) {
e.printStackTrace();
}
// 图片信息追加到内容中
currArticle.append("<p align='center'><img src='").append(imagePath).append("'/></p>").append(System.lineSeparator());
}
}
});
System.out.println(currArticle);
}
}
3. 项目的目录结构如下图