简体   繁体   English

我将两个Word文档与OpenXML SDK合并,但是在将图像复制到标题中时得到了损坏的文档

[英]I am merging two Word documents with OpenXML SDK but get a corrupt document when copying an image into a header

I have code which works in all sorts of different situations, including when copying images into the body of the document. 我有适用于各种不同情况的代码,包括将图像复制到文档正文中时的代码。

The code works when copying (adding) headers and footers from one document to the other, as long as the headers/footers being copied do not contain images. 该代码在将一个文档的页眉和页脚复制(添加)到另一个文档时起作用,只要要复制的页眉/页脚不包含图像即可。

When I copy a header which has an image in it, then the resulting file is corrupt, and when I try to open it with the OpenXML SDK it throws an exception saying "Compressed part has inconsistent data length". 当我复制其中包含图像的标头时,结果文件已损坏,并且当我尝试使用OpenXML SDK打开它时,它将引发异常,指出“压缩部分的数据长度不一致”。 I do know that the image has to be created in the HeaderPart (as against the MainDocumentPart when copying into the body). 我确实知道必须在HeaderPart中创建图像(与复制到正文中时的MainDocumentPart相对)。

The code which does the merging of the image looks something like: 合并图像的代码如下所示:

    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));
      }  
  }

The above is called passing the source and destination HeaderParts, and the XML of the source header which will after this be copied into the destination document. 上面的方法称为传递源头HeaderParts和目标头HeaderParts,以及源头XML,将其复制到目标文档之后。 After calling the above procedure, destinationHeaderPart.Header.Save() is called. 调用上述过程后,将调用destinationHeaderPart.Header.Save()。

As I said above, if there are no images in the source header, then the resulting document is fine (ie when the foreach doesn't find any drawing elements in the source XML). 就像我上面说的,如果源头中没有图像,那么生成的文档就很好了(即,当foreach在源XML中找不到任何绘图元素时)。

I wonder, though, whether this symptom of the images in the header is perhaps a red herring and the real problem is somewhere else. 但是,我不知道标题中图像的这种症状是否可能是红色鲱鱼,而真正的问题在其他地方。

As I said in the comment on the question, the code to include the images into the header and footer was fine - it did the trick. 正如我在对问题的评论中所说的那样,将图像包含在页眉和页脚中的代码很好-它可以解决问题。

How I solved the problem of the corrupt file that my code (elsewhere) was creating was by a bit of trial and error. 我如何解决我的代码(在其他地方)创建的文件损坏的问题,这是经过反复试验的。 As other contributors have said, the documentation around OpenXML is, to put it mildly, not very good. 正如其他贡献者所说的那样,OpenXML的文档并不是很好。 So there might be another resolution to this problem, and maybe my "solution" just works because of some other side effects. 因此,对于这个问题可能还有另一种解决方案,也许由于其他一些副作用,我的“解决方案”才行得通。

Anyway, I have some code which looks like this: 无论如何,我有一些看起来像这样的代码:

    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);
    }

If I call the ReopenDocument method immediately prior to writing the _memoryStream to a FileStream, then the corruption is avoided. 如果在将_memoryStream写入FileStream之前立即调用ReopenDocument方法,则可以避免损坏。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM