You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Apache POI生成带水印Docx文件打开报错:header4.xml XML声明问题

问题分析与解决方案

问题现象

使用Apache POI 3.10 + Java 1.6生成带水印的Docx文件,下载后用Word打开时提示:

Office Open XML文件无法打开,因为内容存在问题
具体描述为“text/xml声明只能出现在输入的最开头”,位置为word/header4.xml

但浏览器的Docx查看器可正常显示内容、页眉及水印。

原因分析

Apache POI 3.10版本较老旧,其XWPFHeaderFooterPolicy.createWatermark()方法在生成或修改页眉XML时,可能出现XML声明位置错误(比如声明前有空白字符)或重复声明的情况。Word的XML解析器对格式要求严格,会触发报错;而浏览器查看器容错性较高,能正常解析。

解决方案

方案1:手动修复页眉XML格式

通过代码获取页眉的XML内容,确保XML声明仅出现一次且位于内容最开头:

XWPFHeaderFooterPolicy headerFooterPolicy = doc.getHeaderFooterPolicy();
headerFooterPolicy.createWatermark("Watermark");

// 遍历所有页眉,修复XML声明问题
for (XWPFHeader header : headerFooterPolicy.getHeaders()) {
    String xml = header.getHeaderElement().getXML();
    // 移除开头的空白字符
    xml = xml.trim();
    // 移除重复的XML声明(只保留第一个)
    int declEndIndex = xml.indexOf("?>") + 2;
    String validXmlStart = xml.substring(0, declEndIndex);
    String xmlRest = xml.substring(declEndIndex).replaceAll("<\\?xml[^>]*\\?>", "");
    xml = validXmlStart + xmlRest;
    // 更新页眉XML
    header.getHeaderElement().setXML(xml);
}

ByteArrayOutputStream baos = new ByteArrayOutputStream();
doc.write(baos);
PortletResponseUtil.sendFile(request, res, outputFile, baos.toByteArray(), contentType);

方案2:升级Apache POI版本

如果Java 1.6环境允许,可升级到Apache POI 3.17(支持Java 1.6的最后稳定版本之一),新版本修复了此类XML生成的兼容性问题,无需手动修改代码即可解决报错。

内容的提问来源于stack exchange,提问作者FireHe4d

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 01:45:26