私は2つの単語文書をOpenXML SDKでマージしていますが、画像をヘッダーにコピーするときに破損した文書を入手しています
-
09-12-2019 - |
質問
私は、文書の本文に画像をコピーするときなど、あらゆる種類のさまざまな状況で機能するコードがあります。
コピーされているヘッダー/フッターに画像が含まれていない限り、1つの文書からヘッダーとフッターをコピー(追加)したときにコードが機能します。
イメージを持つヘッダーをコピーすると、結果のファイルは破損しています.OpenXML SDKで開こうとすると、「圧縮部分が矛盾するデータ長が矛盾している」という例外をスローします。 私は、イメージがヘッダーパートで作成されなければならないことを知っています(本文にコピーするときの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));
}
}
.
上記は、ソースおよび宛先のヘッダパートを渡し、その後のソースヘッダのXMLは宛先文書にコピーされます。上記の手順を呼び出した後、DestinationHeaderPart.Header.save()が呼び出されます。
上記のように、ソースヘッダに画像がない場合、結果の文書は問題ありません(すなわち、foreachがソースXMLに描画要素を見つけられない場合)。
私は、ヘッダー内の画像のこの症状がおそらく赤のニシンであるかどうか、そして本当の問題は他のどこかであるのだろうか。
解決
質問についてのコメントで、画像を含むコードとフッターには素晴らしかったコードです - それはトリックをしました。
私のコード(他の場所)が作成されていた破損ファイルの問題は、少し試行錯誤によって解決されました。他の貢献者が言ったように、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に書き込む直前に再び上書き方法を呼び出すと、破損は回避されます。