编辑 OpenXML docx 模板并将其 return 作为 FileResult
Edit OpenXML docx template and return it as FileResult
我想为我的应用程序的用户提供下载一个 docx 文件的机会,该文件将根据他们的请求包含动态内容。
我用 header 准备了一个模板,否则 OpenXML 的创建在某个地方会很痛苦。
现在我在编辑它并在我的 ASP MVC 应用程序中将其 return 作为 FileResult 时遇到问题。
我的计划是将文件读取到 MemoryStream
并将其编辑为 WordprocessingDocument
,然后 returning MemoryStream as Byte[]
。
我这里有两个问题:
- 如果我在没有内存流的情况下直接从文件读取
WordprocessingDocument
,我看不到将其转换为 FileResult()
想要的形状的方法。
- 如果我用空
MemoryStream
创建新的 WordprocessingDocument
我可以简单地创建内容并将其 return 作为 File
但我缺少之前准备好的 header与所需的内容。
那么,如何编辑 .docx
模板并将其return 编辑为 FileResult()
?
这就是您如何使用 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();
}
在 FortyTwo 的帮助下,我实现了目标。
所以想要的"workflow"是:
- 将
.docx
模板(添加 headers 或其他内容)复制到内存中
- 编辑文档内容
- return 此文档为
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
生效
- 当 return 编辑文件时,您必须使用
.ToArray()
否则 return 编辑的文件已损坏
我想为我的应用程序的用户提供下载一个 docx 文件的机会,该文件将根据他们的请求包含动态内容。 我用 header 准备了一个模板,否则 OpenXML 的创建在某个地方会很痛苦。 现在我在编辑它并在我的 ASP MVC 应用程序中将其 return 作为 FileResult 时遇到问题。
我的计划是将文件读取到 MemoryStream
并将其编辑为 WordprocessingDocument
,然后 returning MemoryStream as Byte[]
。
我这里有两个问题:
- 如果我在没有内存流的情况下直接从文件读取
WordprocessingDocument
,我看不到将其转换为FileResult()
想要的形状的方法。 - 如果我用空
MemoryStream
创建新的WordprocessingDocument
我可以简单地创建内容并将其 return 作为File
但我缺少之前准备好的 header与所需的内容。
那么,如何编辑 .docx
模板并将其return 编辑为 FileResult()
?
这就是您如何使用 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();
}
在 FortyTwo 的帮助下,我实现了目标。
所以想要的"workflow"是:
- 将
.docx
模板(添加 headers 或其他内容)复制到内存中 - 编辑文档内容
- return 此文档为
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
生效
- 当 return 编辑文件时,您必须使用
.ToArray()
否则 return 编辑的文件已损坏