我正在使用OpenXML SDK合并两个Word文档,但在将图像复制到标题时会出现损坏的文档

时间:2012-03-08 12:04:21

标签: c# openxml wordprocessingml

我的代码适用于各种不同的情况,包括将图像复制到文档正文中。

只要复制的页眉/页脚不包含图像,代码就可以在将页眉和页脚从一个文档复制(添加)到另一个文档时起作用。

当我复制其中包含图像的标题时,结果文件已损坏,当我尝试使用OpenXML SDK打开它时,它会抛出一个异常,说“压缩部分的数据长度不一致”。 我知道必须在HeaderPart中创建图像(在复制到正文时与MainDocumentPart相对)。

合并图像的代码如下所示:

    private void AddSourceImagesToDestination(XElement sourceXml, OpenXmlPart sourcePart, OpenXmlPart destPart) {
      foreach(XElement drawingElement in sourceXml.Descendants(_mswDrawingElementName)) {

        XAttribute aBlipEmbedAttribute = drawingElement.Descendants(_ablipElementName).First().Attribute(_embedAttributeName);
        string relationshipId = aBlipEmbedAttribute.Value;
        ImagePart sourceImagePart = (ImagePart)sourcePart.GetPartById(relationshipId);
        ImagePart destinationImagePart = ((HeaderPart)destPart).AddImagePart(sourceImagePart.ContentType);
        string newRelationshipId = destPart.GetIdOfPart(destinationImagePart);
        aBlipEmbedAttribute.SetValue(newRelationshipId);

        destinationImagePart.FeedData(sourceImagePart.GetStream(FileMode.Open, FileAccess.Read));
      }  
  }

上面的内容称为传递源和目标HeaderParts,以及源头文件的XML,在此之后将其复制到目标文档中。调用上述过程后,将调用destinationHeaderPart.Header.Save()。

如上所述,如果源标头中没有图像,那么生成的文档就可以了(即当foreach在源XML中找不到任何绘图元素时)。

我想知道,标题中图像的这种症状是否可能是红鲱鱼,真正的问题是在其他地方。

1 个答案:

答案 0 :(得分:4)

正如我在关于这个问题的评论中所说的那样,将图像包含在页眉和页脚中的代码很好 - 它就是诀窍。

我如何解决我的代码(其他地方)正在创建的损坏文件的问题是通过一些试验和错误。正如其他贡献者所说,围绕OpenXML的文档,温和地说,并不是很好。所以这个问题可能还有另一个解决方案,也许我的“解决方案”因其他一些副作用而起作用。

无论如何,我有一些看起来像这样的代码:

    private MemoryStream _memoryStream;
    private WordprocessingDocument _wordDocument;
      ...
    _wordDocument = WordprocessingDocument.Open(_memoryStream, true);
      ... 

    private void ReopenDocument() {
      _wordDocument.Package.Flush();
      _wordDocument.Close();
      MemoryStream newStream = new MemoryStream();
      _memoryStream.WriteTo(newStream);
      _memoryStream.Close();
      _memoryStream = newStream;
      _memoryStream.Position = 0L;
      _wordDocument = WordprocessingDocument.Open(_memoryStream, true);
    }

如果我在将_memoryStream写入FileStream之前立即调用ReopenDocument方法,则会避免损坏。