使用OpenXml调用AddAlternativeFormatImportPart后损坏文档

本文关键字:损坏 文档 AddAlternativeFormatImportPart OpenXml 调用 使用 | 更新日期: 2023-09-27 18:18:37

我试图在.docx文件中创建一个AddAlternativeFormatImportPart,以便通过AltChunk在文档中引用它。问题是下面的代码导致docx文件被Word损坏,无法打开。

        string html = "some html code."
        string altChunkId = "html234";
        var document = WordprocessingDocument.Open(inMemoryPackage, true);
        var mainPart = document.MainDocumentPart.Document;
        var mainDocumentPart = document.MainDocumentPart;
        AlternativeFormatImportPart chunk = mainDocumentPart.AddAlternativeFormatImportPart
            (AlternativeFormatImportPartType.Xhtml, altChunkId);
        Stream contentStream = chunk.GetStream(FileMode.Open,FileAccess.ReadWrite);
        StreamWriter contentWriter = new StreamWriter(contentStream);
        contentWriter.Write(html);
        contentWriter.Flush();
        {
          ...
        }
        mainPart.Save();

使用OpenXml调用AddAlternativeFormatImportPart后损坏文档

我认为这可能是你如何处理来自AlternativeFormatImportPart的流。尝试使用FeedData代替,就像我下面的例子。

        StringBuilder xhtmlBuilder = new StringBuilder();
        xhtmlBuilder.Append("<html>");
        xhtmlBuilder.Append("<body>");
        xhtmlBuilder.Append("<b>Hello world!</b>");
        xhtmlBuilder.Append("</body>");
        xhtmlBuilder.Append("</html>");
        using (WordprocessingDocument doc = WordprocessingDocument.Open(inputFilePath, true))
        {
            string altChunkId = "chunk1";
            AlternativeFormatImportPart chunk = doc.MainDocumentPart.AddAlternativeFormatImportPart
                (AlternativeFormatImportPartType.Xhtml, altChunkId);
            using (MemoryStream xhtmlStream = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(xhtmlBuilder.ToString())))
            {
                chunk.FeedData(xhtmlStream);
                AltChunk altChunk = new AltChunk();
                altChunk.Id = altChunkId;
                doc.MainDocumentPart.Document.Body.Append(altChunk);
            }
            doc.MainDocumentPart.Document.Save();
        }

我认为这是因为您无法将AltChunk导入到从内存流打开的文档中。我也有同样的问题。我从内存流中打开模板,如下所示:

Private Sub UpdateDoc(templatePath As String)
    Using fs As FileStream = File.OpenRead(templatePath)
        Using ms As New MemoryStream
            CopyStream(fs, ms)
            Using doc As WordprocessingDocument = WordprocessingDocument.Open(ms, True)
                'update the document
                doc.MainDocumentPart.Document.Save()
            End Using
        End Using
    End Using
End Sub
Private Sub CopyStream(source As Stream, target As Stream)
    Dim buffer() As Byte
    Dim bytesRead As Integer = 1
    ReDim buffer(32768)
    While bytesRead > 0
        bytesRead = 0
        bytesRead = source.Read(buffer, 0, buffer.Length)
        target.Write(buffer, 0, bytesRead)
    End While
End Sub

这适用于内容控件等的正常更新,当流回客户端或保存为docx时,文档很好。但是当插入AltChunk时,它会破坏文档。

当插入AltChunk时,从物理文件路径打开文档,如下所示:

    Using doc As WordprocessingDocument = WordprocessingDocument.Open(strTempFile, True)
        Dim altChunkId As String = "AltChunkId1"
        Dim mainDocPart As MainDocumentPart = doc.MainDocumentPart
        Dim chunk As AlternativeFormatImportPart = mainDocPart.AddAlternativeFormatImportPart(AlternativeFormatImportPartType.Xhtml,
                                                                altChunkId)
        Dim strHTML As String = "<html><head/><body><h1>Html Heading</h1><p>This is an html document in a string literal.</p></body></html>"
        Using chunkStream As Stream = chunk.GetStream(FileMode.Create, FileAccess.Write)
            Using sr As StreamWriter = New StreamWriter(chunkStream)
                sr.Write(strHTML)
            End Using
        End Using
        Dim altChunk As New AltChunk
        altChunk.Id = altChunkId
        mainDocPart.Document.Body.InsertAfter(altChunk, mainDocPart.Document.Body.Elements(Of Paragraph)().Last())
        mainDocPart.Document.Save()
    End Using

似乎您不能将AltChunk导入内存流,您只能在打开物理文件进行写入时才能这样做。有人能解释一下这件事吗?

我知道这是一个旧的帖子,但我有同样的问题。当在文件中使用AltChunk时,它会起作用,但在MemoryStream中不起作用。如果有人知道这事就太好了。这就是我如何启动WordprocessingDocument

var byteArrayWithFileFrom360 = ProcessFileHandler.GetFileContent(204735);
var wordDocMemoryStream = new MemoryStream();
wordDocMemoryStream.Write(byteArrayWithFileFrom360, 0, byteArrayWithFileFrom360.Length);
var myDoc = WordprocessingDocument.Open(wordDocMemoryStream, true);