1. 简介

在日常办公自动化开发中,常常需要对 Word 文档中的图片进行批量提取、保存,甚至将图片替换为自定义的文本或链接。Apache POI 是一款强大的 Java 开源库,支持对 Microsoft Office 文档(包括 Word、Excel、PowerPoint 等)进行读写操作。本文将介绍如何使用 POI 提取 Word 文档中的图片,并将图片在文档中替换为自定义文本。

2. 环境准备

  • JDK 1.8+
  • Maven/Gradle(推荐使用 Maven 管理依赖)
  • POI 依赖

Maven 依赖示例:

<dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>5.2.3</version>
</dependency>

3. 提取图片

3.1 基本思路

  1. 使用 XWPFDocument 加载 Word 文档(.docx)。
  1. 通过 getAllPictures() 方法获取文档中所有图片数据。
  1. 将图片数据保存到本地磁盘。

3.2 示例代码

import org.apache.poi.xwpf.usermodel.*;
import java.io.*;
import java.nio.file.*;
import java.util.List;public class WordImageExtractor {public static void extractImages(String docxPath, String outputDir) throws Exception {try (FileInputStream fis = new FileInputStream(docxPath);XWPFDocument document = new XWPFDocument(fis)) {List<XWPFPictureData> pictures = document.getAllPictures();int index = 1;for (XWPFPictureData picture : pictures) {String ext = picture.suggestFileExtension();byte[] data = picture.getData();String fileName = "image_" + index++ + "." + ext;Path imagePath = Paths.get(outputDir, fileName);Files.write(imagePath, data);System.out.println("图片已保存: " + imagePath);}}}
}

4. 替换图片为自定义文本

4.1 基本思路

  1. 遍历文档的所有段落和 run。
  1. 检查 run 是否包含图片(getEmbeddedPictures())。
  1. 删除包含图片的 run,并插入新的 run,写入自定义文本(如图片路径或占位符)。

4.2 示例代码

public static void replaceImagesWithText(String docxPath, String outputPath, String replacementText) throws Exception {try (FileInputStream fis = new FileInputStream(docxPath);XWPFDocument document = new XWPFDocument(fis)) {for (XWPFParagraph paragraph : document.getParagraphs()) {List<XWPFRun> runs = paragraph.getRuns();for (int i = runs.size() - 1; i >= 0; i--) {XWPFRun run = runs.get(i);if (!run.getEmbeddedPictures().isEmpty()) {paragraph.removeRun(i);XWPFRun newRun = paragraph.insertNewRun(i);newRun.setText(replacementText);}}}try (FileOutputStream fos = new FileOutputStream(outputPath)) {document.write(fos);}System.out.println("图片已替换,文档保存为: " + outputPath);}
}

5. 综合示例:提取并替换

将图片提取到本地后,用图片的本地路径替换文档中的图片:

//找到拆分文档中的图片 并进行占位符的替换InputStream docStream = new FileInputStream(fullPath);int index = 0;String newFileName = "processed_" + fileName;String outputPath = outputDir + "/" + newFileName;try (XWPFDocument document = new XWPFDocument(docStream)) {List<XWPFPictureData> pictures = document.getAllPictures();System.out.println("提取到的图片数量: " + pictures.size());// 保存图片并记录图片信息Map<String, String> picturePathMap = new HashMap<>();for (XWPFPictureData pictureData : pictures) {try {byte[] data = pictureData.getData();BufferedImage originalImage = ImageIO.read(new ByteArrayInputStream(data));if (originalImage != null) {// 获取图片格式String fileExtension = pictureData.suggestFileExtension();// 生成保存路径String outputPath = String.format("%s/image_%d_%s.%s",outputDir,++index,fileName,fileExtension);// 保存图片File outputFile = new File(outputPath);// 如果ImageIO不支持该格式,直接保存原始字节数据if (!outputFile.exists() || outputFile.length() == 0) {Files.write(Paths.get(outputPath), data);// 记录图片ID和路径的映射picturePathMap.put(pictureData.getPackagePart().getPartName().getName(),outputPath);}System.out.println(String.format("已保存第 %d 张图片: %s", index, outputPath));}} catch (Exception e) {System.err.println("处理第 " + (index + 1) + " 张图片时出错: " + e.getMessage());}}// 处理文档中的段落,替换图片为文本for (XWPFParagraph paragraph : document.getParagraphs()) {List<XWPFRun> runs = paragraph.getRuns();for (int k = runs.size() - 1; k >= 0; k--) {XWPFRun run = runs.get(k);List<XWPFPicture> pictures2 = run.getEmbeddedPictures();if (!pictures2.isEmpty()) {// 获取图片路径String picturePath = picturePathMap.get(pictures2.get(0).getPictureData().getPackagePart().getPartName().getName());if (picturePath != null) {// 删除当前run中的内容paragraph.removeRun(k);// 创建新的run并添加文本XWPFRun newRun = paragraph.insertNewRun(k);newRun.setText("[图片地址: " + picturePath + "]");}}}}// 保存修改后的文档try (FileOutputStream fos = new FileOutputStream(outputPath)) {document.write(fos);}FileUtil.del(fullPath);System.out.println("处理完成,新文档保存为: " + outputPath);}

6. 注意事项

  • 只支持 .docx 格式(.doc 需用 HWPF,API 不同)。
  • 图片提取顺序与文档中出现顺序一致,但图片与 run 的映射需通过 getPackagePart().getPartName().getName() 匹配。
  • 替换时建议从后往前遍历 run,避免索引错乱。

7. 总结

通过 Apache POI,可以方便地实现 Word 文档图片的批量提取和替换。实际开发中可根据业务需求,灵活调整图片保存路径、替换文本等逻辑。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/87385.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/87385.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/87385.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

毫米波雷达 – 深度学习

目录 数据表示 公开数据库 未来发展方向 稀疏点云 + 深度学习 直接处理点云 (1/2) 候选生成+特征提取+候选分类(DL* ) 候选生成+特征提取+候选分类(DL) 直接处理点云 (2/2) 候选生成+特征提取(DL)+候选分类(DL) 网格数据+端对端检测(DL) 稠密数据块 + 深度学习 直接…

Redis——常用指令汇总指南(一)

目录 1.set & get ①set指令 ②get指令 2.keys 3.del 4.expire & setex & psetex 5.ttl 6.exists 7.setnx 8.flushall 9.object encoding 10. type 1.set & get set & get指令中key和value都是字符串&#xff0c;但是不需要加单引号或双引号。 …

PDF处理控件Aspose.PDF教程:在 Java 中删除 PDF 页面

您是否需要使用 Java 从PDF文档中删除特定页面&#xff1f;无论您是要清理空白页、删除机密部分&#xff0c;还是仅仅在分发前调整内容&#xff0c;以编程方式操作 PDF 页面的能力都将大有裨益。本指南将向您展示如何借助Aspose.PDF仅用几行代码删除不需要的页面。让我们深入了…

RediSearch 字段类型与配置选项

1. 数值字段&#xff08;NUMERIC&#xff09; 用途&#xff1a;存储整数或浮点数&#xff0c;可进行范围查询与排序。 选项&#xff1a; SORTABLE&#xff1a;允许用 SORTBY 排序NOINDEX&#xff1a;不参与索引&#xff0c;仅供返回 定义语法 FT.CREATE idx ON HASH PREFIX…

PHP Yii2 安装SQL Server扩展-MAC M4 Pro芯片

MAC M4 Pro芯片版本&#xff0c;千锤百炼编译十几次终于成功 # 设置基础镜像并强制使用 x86_64 架构&#xff08;适配 M4 芯片&#xff09; FROM --platformlinux/amd64 php:8.1-fpm-alpine3.18WORKDIR /var/www/html# 可选&#xff1a;设置时区 ARG TZAsia/Shanghai ENV TZ${…

HTML初学者第二天

<1>HTML的语法规范 1.1标签 -双标签&#xff1a;如 <html></html> 前面的叫开始标签&#xff0c;后面的叫结束标签。 -单标签&#xff1a;如 <br /> 1.2基本语法概述 -HTML标签是由尖括号包围的关键词&#xff0c;例如<html>。 -HTML标…

【加解密与C】HASH系列(二) SHA

SHA&#xff08;安全散列算法&#xff09;简介 SHA&#xff08;Secure Hash Algorithm&#xff09;是由美国国家安全局&#xff08;NSA&#xff09;设计的一系列密码散列函数&#xff0c;用于将任意长度的数据转换为固定长度的散列值。SHA家族包括SHA-1、SHA-2&#xff08;含S…

【Python】进阶 - 数据结构与算法

系列篇章&#x1f389; No.文章1【Python】基础知识&#xff08;详细&#xff09;&#x1f680;2【Python】基础 - 循环、容器类型&#x1f680;3【Python】基础 - 推导式、函数&#x1f680;4【Python】基础 - 文件、异常、模块&#x1f680;5【Python】进阶 - 面向对象&…

【如何实现分布式压测中间件】

分布式压测中间件的原理及其实现 原理全链路追踪框架&#xff08;Trace&#xff09;MQ中间件数据库分布式缓存中间件&#xff08;Redis&#xff09;分库分表中间件 原理 通过大量阅读中间件源码&#xff0c;开源社区调研&#xff0c;得到设计原理&#xff1a; &#xff08;1&a…

Qt进程间保活方案:详解如何实现进程间通信与自动保活机制

目录 摘要 一、进程间保活的基本原理 二、具体步骤及代码示例 三、常见问题与优化 四、总体方案 摘要 在一些需要长时间运行的应用程序中&#xff0c;确保进程在意外退出时能够自动重启是一项非常重要的任务。尤其是在嵌入式开发、后台服务以及需要高可用性的场景下&#x…

Python-内置数据结构-list-tuple-bubble-字符串-bytes-bytesarray-切片-学习笔记

欠4年前自己的一份笔记&#xff0c;献给今后的自己。 分类 数值型 int、float、complex、bool 序列对象 字符串 str 列表 list tuple 键值对 集合set 字典dict 数值型 int、float、complex、bool都是class&#x…

利用事务钩子函数解决业务异步发送问题

利用事务钩子函数解决业务异步发送问题 一、问题背景二、实现方案1、生产者代码2、消费者代码 三、测试与验证1、未开启事务场景2、开启事务场景 四、项目结构及源码 一、问题背景 在某项业务中&#xff0c;需要在事务完成后&#xff0c;写入日志到某数据库中。需要要么都成功&…

uniapp选择相册

概述 一款针对Android平台下的图片选择器&#xff0c;支持从相册获取图片、视频、音频&拍照&#xff0c;支持裁剪(单图or多图裁剪)、压缩、主题自定义配置等功能&#xff0c;支持动态获取权限&适配Android 5.0系统的开源图片选择框架。 支持Uniapp和Uniapp X下的Vue2、…

MAC 多应用切换技巧,单应用切换技巧

在 Mac 上&#xff0c;有几种快捷键可以帮助你快速切换应用程序窗口&#xff1a; 1. Command (⌘) Tab - 这是最常用的快捷键&#xff0c;用于在打开的应用程序之间进行循环切换。按住 Command 键不放&#xff0c;然后反复按下 Tab 键可以选择下一个应用程序。当你松开 Comm…

SpringBoot+本地部署大模型实现知识库功能

SpringBoot本地部署大模型实现RAG知识库功能 1、Linux系统部署本地大模型1.1 安装ollama1.2 启动ollama1.3 下载deepseek模型 2、Springboot代码调用本地模型实现基础问答功能3、集成向量数据库4、知识库数据喂取5、最终实现RAG知识库功能 1、Linux系统部署本地大模型 1.1 安装…

嵌入式原理与应用篇---ARM

ARM 架构的 STM32 系列微控制器广泛应用于嵌入式系统开发&#xff0c;理解其汇编语言指令对于优化性能、访问硬件底层非常重要。下面详细解释常见的 ARM 汇编指令及其使用实例。 数据处理指令 1. MOV&#xff08;移动&#xff09; 功能&#xff1a;将立即数或寄存器值复制到…

【RHCSA-Linux考试题目笔记(自用)】servera的题目

一、开始 1、启动rhcsa环境 2、点击题目&#xff0c;看题 3、通过控制器来启动所有虚拟机 控制器 打开后点start&#xff0c;然后ok 之后进入一个有classroom、servera、serverb&#xff08;考试不一定叫这些名&#xff0c;但大差不差&#xff09;什么之类的界面&#xff0c;…

SpringBoot项目使用arthas-tunnel-server

参考官网Arthas Spring Boot Starter | arthas Spring Boot系列之使用Arthas Tunnel Server 进行远程调试实践-腾讯云开发者社区-腾讯云 springBoot项目, 增加maven依赖 <dependency><groupId>com.taobao.arthas</groupId><artifactId>arthas-sprin…

Modbus TCP 进阶:基于以太网的远程设备控制(二)

基于 Modbus TCP 的远程设备控制实战 &#xff08;一&#xff09;硬件与网络搭建实操 1. 设备选型与连接 在工业现场&#xff0c;根据远程控制需求进行设备选型至关重要 。对于传感器&#xff0c;若要监测温度&#xff0c;可选择高精度的热电偶传感器&#xff0c;如 K 型热电…

分库分表之实战-sharding-JDBC

大家好&#xff0c;我是工藤学编程 &#x1f989;一个正在努力学习的小博主&#xff0c;期待你的关注实战代码系列最新文章&#x1f609;C实现图书管理系统&#xff08;Qt C GUI界面版&#xff09;SpringBoot实战系列&#x1f437;【SpringBoot实战系列】Sharding-Jdbc实现分库…