【问题标题】:Trying to create an in memory Word Doc with OpenXml says it's corrupt尝试使用 OpenXml 创建内存中的 Word Doc 说它已损坏
【发布时间】:2016-01-12 18:51:48
【问题描述】:

我已经构建了一个 ActionResult 来将数据输出到 Word 文档。我在编译或运行时没有收到任何错误,但在尝试打开文件时我收到消息:'很抱歉,我们无法打开 filename.docx,因为我们发现其内容有问题。'。

这是我想要做的:

public override void ExecuteResult(ControllerContext context)
{
    //Create a response stream to create and write the Excel file
    HttpContext curContext = HttpContext.Current;
    curContext.Response.Clear();
    curContext.Response.AddHeader("content-disposition", "attachment;filename=text.docx");
    curContext.Response.Charset = "";
    curContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
    curContext.Response.ContentType = "application/vnd.ms-word";

    //Write the stream back to the response
    var ms = new MemoryStream();

    var repData = "<b>Mark's Test Book: With a Special Sub Title</b><br /><br /><b>Chapter: Chapter Title 1: Chapter Title sub</b><br /><br />";

    Document.CreateAndAddHtmlToWordprocessingStream(ms, repData);

    curContext.Response.OutputStream.Write(ms.GetBuffer(), 0, ms.GetBuffer().Length);

    curContext.Response.End();

}

静态方法如下:

public static void CreateAndAddHtmlToWordprocessingStream(Stream stream, string inputBody)
{
    // Open a WordProcessingDocument based on a stream.
    WordprocessingDocument wordprocessingDocument =
        WordprocessingDocument.Create(stream, WordprocessingDocumentType.Document);

    // Add a main document part. 
    MainDocumentPart mainPart = wordprocessingDocument.AddMainDocumentPart();

    // Create the document structure.
    mainPart.Document = new DocumentFormat.OpenXml.Wordprocessing.Document();

    // Create the document body.
    mainPart.Document.AppendChild(new Body());

    var ms = new MemoryStream(System.Text.Encoding.Default.GetBytes("<html><head></head><body style=\"font-family:'Calibri';\">" + inputBody + "</body></html>"));

    var altChunkId = "id";
    var formatImportPart = mainPart.AddAlternativeFormatImportPart(AlternativeFormatImportPartType.Html, altChunkId);

    formatImportPart.FeedData(ms);

    var altChunk = new AltChunk { Id = altChunkId };

    mainPart.Document.Body.Append(altChunk);

    mainPart.Document.Save();

    // Close the document handle.
    wordprocessingDocument.Close();

    // Caller must close the stream.
}

我看过这两个帖子,但没有找到任何帮助:

C# return memory stream from OpenXML resulting to a corrupted word file

Streaming In Memory Word Document using OpenXML SDK w/ASP.NET results in "corrupt" document

【问题讨论】:

  • ms.GetBuffer() 听起来不对...通常你会做ms.Position = 0; 并返回流。如果要先命中字节数组,请使用ms.ToArray()

标签: c# openxml


【解决方案1】:

ms.GetBuffer() 将返回自动管理和调整大小的缓冲区。这将从您写入的数据开始,但可能会在末尾包含额外的 \0 字节,以防您继续 .Write()

要返回MemoryStream,您可以使用以下任一方法:

ms.Position = 0;
ms.CopyTo(curContext.Response.OutputStream);

或:

var msResult = ms.ToArray();
curContext.Response.OutputStream.Write(msResult, 0, msResult.Length);

【讨论】:

  • 我最终这样做了:` ms.WriteTo(curContext.Response.OutputStream);` 并且成功了。谢谢。
  • 我很高兴听到这解决了您的问题,您可以考虑通过单击投票按钮下方的绿色复选标记来接受它。
【解决方案2】:

你可以创建一个这样的方法来处理内存流和文件名格式

private static void DynaGenWordDoc(string fileName, Page page, WordprocessingDocument wdoc)
{
    page.Response.ClearContent();
    page.Response.ClearHeaders();
    page.Response.ContentType = "application/vnd.ms-word";
    page.Response.AppendHeader("Content-Disposition", string.Format("attachment;filename={0}.docx", fileName));

    using (MemoryStream memoryStream = new MemoryStream())
    {
        wdoc.SaveAs(memoryStream);
        memoryStream.WriteTo(page.Response.OutputStream);
        memoryStream.Close();
    }
    page.Response.Flush();
    page.Response.End();
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-13
    相关资源
    最近更新 更多