【问题标题】:Edit OpenXML docx template and return it as FileResult编辑 OpenXML docx 模板并将其作为 FileResult 返回
【发布时间】:2018-03-20 09:10:00
【问题描述】:

我想为我的应用程序的用户提供下载一个 docx 文件,该文件将根据他们的请求包含动态内容。 我准备了一个带有标题的模板,否则 OpenXML 的创建在某处很痛苦。 现在我无法在我的 ASP MVC 应用程序中编辑它并将其作为 FileResult 返回。

我的计划是将文件读取到MemoryStream 并将其编辑为WordprocessingDocument,然后返回MemoryStream as Byte[]

我这里有两个问题:

  1. 如果我直接从没有内存流的文件中读取WordprocessingDocument,我看不到将其转换为FileResult() 想要的形状的方法。
  2. 如果我用空的MemoryStream 创建新的WordprocessingDocument,我可以简单地创建内容并将其作为File 返回,但我缺少先前准备好的带有所需内容的标题。

那么,如何编辑.docx 模板并将其返回为FileResult()

【问题讨论】:

    标签: asp.net asp.net-mvc openxml


    【解决方案1】:

    这就是您如何使用MemoryStream 创建一个新的电子表格文档,然后将其保存到Byte[]

    Byte[] file;
    using (MemoryStream mem = new MemoryStream())
    {
        using (SpreadsheetDocument spreadsheetDocument = 
            SpreadsheetDocument.Create(mem, SpreadsheetDocumentType.Workbook))
        {
            WorkbookPart workbookpart = spreadsheetDocument.AddWorkbookPart();
            workbookpart.Workbook = new Workbook();
            WorksheetPart worksheetPart = workbookpart.AddNewPart<WorksheetPart>();
            worksheetPart.Worksheet = new Worksheet(new SheetData());
    
            Sheets sheets = spreadsheetDocument.WorkbookPart.Workbook.
                AppendChild<Sheets>(new Sheets());
    
            Sheet sheet = new Sheet()
            {
                Id = spreadsheetDocument.WorkbookPart.
                    GetIdOfPart(worksheetPart),
                SheetId = 1,
                Name = "aStupidSheet"
            };
            sheets.Append(sheet);
            workbookpart.Workbook.Save()
            spreadsheetDocument.Close();
        }
        file = mem.ToArray();
    }
    

    【讨论】:

    • 我知道这种方法,但它并没有解决我的问题,因为我想打开模板而不是在 MemoryStream 中创建一个新模板。如果从现有文件中打开它,则无法直接将其转换为 byte[] 而不保存。或者只是我没有看到一个选项。
    • 然后用File.OpenRead将模板读入内存流,然后创建或打开你的spreadsheetDocument
    【解决方案2】:

    在 FortyTwo 的帮助下,我成功实现了目标。

    所以想要的“工作流程”是:

    1. .docx 模板(添加的标题或其他内容)复制到内存中
    2. 编辑文档内容
    3. 将此文档返回为FileResult,而不保存对模板的更改

    代码如下:

    public FileResult EditDOCXBody()
    {
        // Prepare file path
        string file = "../WordTemplates/EmptyTemplate.docx";
        String fullFilePath = HttpContext.ApplicationInstance.Server.MapPath(file);                   
    
        // Copy file content to MemeoryStream via byte array
        MemoryStream stream = new MemoryStream();                          
        byte[] fileBytesArray = System.IO.File.ReadAllBytes(fullFilePath);  
        stream.Write(fileBytesArray, 0, fileBytesArray.Length);             // copy file content to MemoryStream
        stream.Position = 0;                                                
    
        // Edit word document content
        using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(stream, true))  
        {
            MainDocumentPart mainPart = wordDoc.MainDocumentPart;                
            Body body = mainPart.Document.Body;
    
            // add some text to body
            body.Append(new Paragraph(
                        new Run(
                            new Text("Current time is: " + DateTime.Now.ToLongTimeString()))));
    
            // Save changes to reflect on stream object
            mainPart.Document.Save();                
        }
        return File(stream.ToArray(), "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "servedFilename.docx");            
    }
    

    一些重要说明:

    • 您需要手动将文件字节写入 MemoryStream,否则您会收到 Memory stream is not expandable 错误。更多信息here
    • 您必须使用mainPart.Document.Save() 才能使更改在MemoryStream 上生效
    • 返回文件时,必须使用.ToArray(),否则返回的文件已损坏

    【讨论】:

      猜你喜欢
      • 2023-04-10
      • 1970-01-01
      • 2018-12-21
      • 1970-01-01
      • 2011-01-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多