使用OpenXml调用AddAlternativeFormatImportPart后损坏文档

时间:2011-12-23 14:30:14

标签: c# ms-word openxml openxml-sdk docx

我正在尝试在.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();

3 个答案:

答案 0 :(得分:7)

我认为你可能是如何处理来自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();

        }

答案 1 :(得分:3)

我认为这是因为您无法将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时会破坏doc。

在插入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导入内存流,只有在打开物理文件进行写入时才能执行此操作。谁能解释一下这件事?

答案 2 :(得分:0)

我知道这是一个老帖子,但我有同样的问题。 在文件中使用AltChunk时,它可以工作,但在MemoryStream中则不行。 如果有人知道这一点会很棒。这就是我启动WordprocessingDocument

的方法
var byteArrayWithFileFrom360 = ProcessFileHandler.GetFileContent(204735);

var wordDocMemoryStream = new MemoryStream();
wordDocMemoryStream.Write(byteArrayWithFileFrom360, 0, byteArrayWithFileFrom360.Length);

var myDoc = WordprocessingDocument.Open(wordDocMemoryStream, true);