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

如何通过OpenXML删除Word文档自定义属性?文档仍无法打开

修复OpenXML处理损坏Word文档自定义属性后无法打开的问题

问题描述

我尝试用OpenXML删除一个已损坏Word文档的自定义属性,代码能正常编译,但处理后的文档无法打开,弹出错误:

Word found unreadable content in ''. Do you want to recover the contents of this document? if you trust the source of this document, click yes

用户编写的代码如下:

public static MemoryStream DeleteCustomPropertiers(Stream fileStream)
{
    var msStream = new MemoryStream();
    fileStream.CopyTo(msStream);
    using (var document = WordprocessingDocument.Open(msStream, true))
    {
        var properties = new Dictionary<string, string>();
        if (document != null)
        {
            var customProps = document.CustomFilePropertiesPart;
            if (customProps != null)
            {
                if (customProps.Properties != null)
                {
                    var props = from n in customProps.Properties.Elements<CustomDocumentProperty>()
                                where n.Name == "Props1" || n.Name == "Props2"
                                select n;

                    for (int i = props.Count() - 1; i >= 0; i--)
                    {
                        var prop = props.ToList()[i];
                        prop.Remove();
                    }
                    customProps.Properties.Save();
                }
            }
        }
        msStream.Position = 0;
        document.MainDocumentPart.Document.Save();
        document.Dispose();
        return msStream;
    }
}

问题分析与修复方案

1. 移除多余的手动资源释放

using语句会自动释放WordprocessingDocument对象,手动调用document.Dispose()会导致资源提前释放,引发流操作异常,直接删除该语句即可。

2. 修正属性删除逻辑

原代码中LINQ查询每次枚举都会重新获取元素,循环中多次调用ToList()会导致重复查询,且可能触发集合变更异常。应先将需要删除的属性转为List再遍历删除:

var propsToRemove = customProps.Properties.Elements<CustomDocumentProperty>()
                        .Where(n => n.Name == "Props1" || n.Name == "Props2")
                        .ToList();
foreach (var prop in propsToRemove)
{
    prop.Remove();
}

3. 调整流位置设置时机

将msStream.Position = 0移到using块外部,确保文档完全保存并释放资源后,再重置流的读取位置。

4. 启用损坏文档修复模式

原文档本身已损坏,直接用OpenXML操作可能加剧损坏,需启用SDK的修复模式:

var settings = new OpenSettings
{
    RepairMode = RepairMode.Repair
};
using (var document = WordprocessingDocument.Open(msStream, true, settings))
{
    // 后续操作
}

5. 简化文档保存逻辑

不需要单独调用MainDocumentPart.Document.Save(),WordprocessingDocument在using块结束时会自动保存所有变更,单独调用可能导致保存不完整。

修正后的完整代码

public static MemoryStream DeleteCustomProperties(Stream fileStream)
{
    var msStream = new MemoryStream();
    fileStream.CopyTo(msStream);
    
    // 启用修复模式处理损坏文档
    var settings = new OpenSettings
    {
        RepairMode = RepairMode.Repair
    };
    
    using (var document = WordprocessingDocument.Open(msStream, true, settings))
    {
        if (document?.CustomFilePropertiesPart?.Properties != null)
        {
            // 先转为List避免枚举时集合变更异常
            var propsToRemove = document.CustomFilePropertiesPart.Properties
                .Elements<CustomDocumentProperty>()
                .Where(n => n.Name == "Props1" || n.Name == "Props2")
                .ToList();
            
            foreach (var prop in propsToRemove)
            {
                prop.Remove();
            }
            
            // 保存属性部分的变更
            document.CustomFilePropertiesPart.Properties.Save();
        }
    }
    
    // 重置流位置,供后续读取使用
    msStream.Position = 0;
    return msStream;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 06:35:32