【问题标题】:Corrupt document after calling AddAlternativeFormatImportPart using OpenXml使用 OpenXml 调用 AddAlternativeFormatImportPart 后损坏的文档
【发布时间】:2011-12-23 14:30:14
【问题描述】:

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

【问题讨论】:

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


    【解决方案1】:

    我认为这可能是您处理来自 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();
    
            }
    

    【讨论】:

    • :你的回答很有用。你能给我一个提示吗?我不想将html数据输入word文档,我想为相应的html数据获取OOXML格式的字符串.无需更新word文档。我只想要ooxml格式的字符串...
    【解决方案2】:

    我认为这是因为您无法将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 导入内存流,您只能在打开物理文件进行写入时执行此操作。谁能解释一下这个问题?

    【讨论】:

      【解决方案3】:

      我知道这是一个旧帖子,但我有同样的问题。 在文件中使用 AltChunk 时,它有效,但在 MemoryStream 中无效。 如果有人对此有所了解,那就太好了。这就是我启动 WordprocessingDocument 的方式

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-03-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-03-24
        相关资源
        最近更新 更多