java合并多个DOCX文件为主要推荐方法 word图片
package com.baise.web.backend.utils;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.xwpf.usermodel.*;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlOptions;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBody;
import java.io.*;
import java.util.*;
public class DocxMergerUtil {
/**
* 合并多个DOCX文件为主要推荐方法 word图片
*/
public static void mergeDocxFiles(List<String> inputFiles, String outputFile) {
try {
// 确保输出目录存在
File output = new File(outputFile);
output.getParentFile().mkdirs();
if (inputFiles == null || inputFiles.isEmpty()) {
throw new IllegalArgumentException("输入文件列表不能为空");
}
try (FileOutputStream dest = new FileOutputStream(output)) {
List<XWPFDocument> documentList = new ArrayList<>();
// 加载所有文档并保持它们打开状态直到处理完成
List<OPCPackage> packageList = new ArrayList<>();
try {
for (String filePath : inputFiles) {
FileInputStream in = new FileInputStream(filePath);
OPCPackage open = OPCPackage.open(in);
packageList.add(open);
XWPFDocument document = new XWPFDocument(open);
documentList.add(document);
}
// 以第一个文档为基础进行合并
XWPFDocument baseDoc = documentList.get(0);
// 合并其余文档
for (int i = 1; i < documentList.size(); i++) {
// 在文档之间添加分页符
documentList.get(i).createParagraph().setPageBreak(true);
try {
appendDocument(baseDoc, documentList.get(i));
} catch (Exception e) {
System.out.println("文件合并error !" + e);
}
}
// 写入最终文档
baseDoc.write(dest);
System.out.println("文件合并完成!");
} finally {
// 确保所有包都被正确关闭
for (OPCPackage pkg : packageList) {
try {
pkg.close();
} catch (Exception e) {
// 忽略关闭异常
}
}
}
}
} catch (Exception e) {
System.out.println("文件合并error !" + e);
}
}
/**
* 将源文档内容追加到目标文档
* 参考WordMerger的实现方式优化
*/
private static void appendDocument(XWPFDocument target, XWPFDocument source) throws Exception {
CTBody targetBody = target.getDocument().getBody();
CTBody sourceBody = source.getDocument().getBody();
// 复制图片并建立映射关系
Map<String, String> pictureRelationMap = new HashMap<>();
List<XWPFPictureData> allPictures = source.getAllPictures();
// 预先读取所有图片数据以避免延迟加载问题
Map<String, byte[]> pictureDataMap = new HashMap<>();
Map<String, Integer> pictureTypeMap = new HashMap<>();
for (XWPFPictureData picture : allPictures) {
String relationId = source.getRelationId(picture);
// 立即读取图片数据,避免延迟加载问题
byte[] data = picture.getData();
pictureDataMap.put(relationId, data);
pictureTypeMap.put(relationId, picture.getPictureType());
}
// 添加图片到目标文档
for (Map.Entry<String, byte[]> entry : pictureDataMap.entrySet()) {
String oldRelationId = entry.getKey();
byte[] data = entry.getValue();
int pictureType = pictureTypeMap.get(oldRelationId);
String newRelationId = target.addPictureData(data, pictureType);
pictureRelationMap.put(oldRelationId, newRelationId);
}
// 合并文档内容
appendBody(targetBody, sourceBody, pictureRelationMap);
}
/**
* 合并两个文档的body部分,并更新图片引用
* 基于WordMerger的实现方式
*/
private static void appendBody(CTBody target, CTBody source, Map<String, String> pictureRelationMap) throws Exception {
try {
XmlOptions optionsOuter = new XmlOptions();
optionsOuter.setSaveOuter();
String sourceXml = source.xmlText(optionsOuter);
String targetXml = target.xmlText();
// 提取XML各部分
String prefix = targetXml.substring(0, targetXml.indexOf(">") + 1);
String mainPart = targetXml.substring(targetXml.indexOf(">") + 1, targetXml.lastIndexOf("<"));
String suffix = targetXml.substring(targetXml.lastIndexOf("<"));
String addPart = sourceXml.substring(sourceXml.indexOf(">") + 1, sourceXml.lastIndexOf("<"));
// 更新图片引用ID
if (pictureRelationMap != null && !pictureRelationMap.isEmpty()) {
for (Map.Entry<String, String> entry : pictureRelationMap.entrySet()) {
addPart = addPart.replace(entry.getKey(), entry.getValue());
}
}
// 解析合并后的XML并设置到目标文档
CTBody mergedBody = CTBody.Factory.parse(prefix + mainPart + addPart + suffix);
target.set(mergedBody);
} catch (XmlException e) {
System.out.println("XML解析错误:" + e);
}
}
public static void main(String[] args) {
try {
List<String> files = Arrays.asList(
"/Users/docs/11.docx",
"/Users/docs/22.docx"
);
String output = "/Users/docs/1122.docx";
// 使用优化后的方法
mergeDocxFiles(files, output);
System.out.println("文件合并完成!");
} catch (Exception e) {
System.err.println("合并文件时出错: " + e.getMessage());
e.printStackTrace();
}
}
}
本文来自博客园,作者:年少轻狂请多指教,转载请注明原文链接:https://www.cnblogs.com/HAILAER/p/19004317
浙公网安备 33010602011771号