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

如何用XDocument修改docx节点后保存为流并上传至Microsoft Graph

解决XDocument修改docx后文件损坏的问题

你的问题根源有两个:

  • 直接把主文档的XML读取为字符串再用XDocument解析保存,丢失了docx作为压缩包的其他关键部件(比如样式、设置、媒体文件等),相当于只保留了主文档内容,破坏了整个docx的结构。
  • XDocument在解析无默认命名空间的XML时,会自动补全命名空间声明,导致生成的XML不符合OOXML规范,Word无法识别。

正确的做法是直接通过WordprocessingDocument操作主文档的XDocument,并完整保存整个docx包,而不是单独提取主文档XML:

using (var memoryStream = await oneDrive.DriveItemDownloadAsync(SharedDriveID, filePathSourceMemo, "path"))
{
    // 先把下载的流复制到新内存流,避免原流被占用导致异常
    var workingStream = new MemoryStream();
    await memoryStream.CopyToAsync(workingStream);
    workingStream.Position = 0;

    var uploadStream = new MemoryStream();

    using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(workingStream, true))
    {
        // 直接获取主文档的XDocument,自动处理OOXML命名空间
        var xDoc = wordDoc.MainDocumentPart.GetXDocument();

        // 在这里执行你的节点修改操作,示例:
        // var body = xDoc.Descendants(W.body).FirstOrDefault();
        // if (body != null) { /* 你的修改逻辑 */ }

        // 把修改后的XDocument保存回主文档部件
        wordDoc.MainDocumentPart.PutXDocument(xDoc);

        // 把完整的docx包保存到上传用的流
        wordDoc.SaveAs(uploadStream);
    }

    uploadStream.Position = 0;
    var UploadResponse = await oneDrive.UploadFileStreamAsync(SharedDriveID, uploadStream, filePathDestinationMemo, "replace");
}

关键说明:

  • 使用GetXDocument()和PutXDocument()方法(需引用DocumentFormat.OpenXml.Packaging命名空间),这两个方法会严格遵循OOXML规范处理命名空间,不会额外添加多余的xmlns声明。
  • 必须完整保存整个WordprocessingDocument到上传流,不能只单独保存主文档的XML,这样才能保留docx压缩包的所有部件,保证文件结构完整。
  • 下载的流要先复制到新内存流,因为WordprocessingDocument.Open会占用原流的位置指针,直接使用可能导致后续操作异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 01:20:03