NPOI - 保存到文件后.xlsx工作簿损坏



我用这段代码写了一个令人兴奋的excel文件。写入文件后,当我手动打开文件时,它已损坏。我正在使用 NPOI 二进制 2.3.0.0 请告诉如何避免 excel 损坏。

[Authorize]
public void ExportUsers()
{
var path = Server.MapPath(@"~ContentExportTemplates") + "sample.xlsx";
FileStream sw = new FileStream(path, FileMode.Open, FileAccess.Read);
IWorkbook workbook = WorkbookFactory.Create(sw);       
ISheet sheet = workbook.GetSheetAt(0);
IRow row = sheet.GetRow(12);
ICell cell = row.CreateCell(row.LastCellNum);
cell.SetCellValue("test");
workbook.CreateSheet("Ripon");            
sw.Close();
using (var exportData = new MemoryStream())
{
workbook.Write(exportData);
string saveAsFileName = string.Format("Export-{0:d}.xls", DateTime.Now).Replace("/", "-");
System.Web.HttpContext.Current.Response.ContentType = "application/vnd.ms-excel";
System.Web.HttpContext.Current.Response.AddHeader("Content-Disposition", string.Format("attachment;filename={0}", saveAsFileName));
System.Web.HttpContext.Current.Response.Clear();
System.Web.HttpContext.Current.Response.BinaryWrite(exportData.GetBuffer());
System.Web.HttpContext.Current.Response.End();                    
}
}

新文件已创建,但已损坏。我见过有人说这在 2.0.6 版中已修复,但仍然对我不起作用

这里有几个问题。

首先,您从.xlsx文件开始,然后将下载文件扩展名更改为.xls.xls.xlsx的文件格式不同;前者是二进制格式,而后者是压缩的XML格式。 如果使用错误的扩展名保存文件,则 Excel 将在打开文件时报告文件已损坏。

其次,您使用了错误的方法从MemoryStream获取数据。GetBuffer将返回整个分配的内部缓冲区数组,如果缓冲区未完全填满,则将包括超出数据末尾的任何未使用的字节。 额外的空字节将导致下载的文件损坏。 如果只想获取缓冲区中的数据,则应改用ToArray

第三,看起来您正在使用 ASP.NET MVC 框架(基于方法上是否存在[Authorize]属性),但您直接操作当前响应,而不是使用控制器的内置File方法来返回可下载文件。 我建议尽可能使用内置方法,因为它会使您的代码更加干净。

以下是更正后的代码:

[Authorize]
public ActionResult ExportUsers()
{
var path = Server.MapPath(@"~ContentExportTemplates") + "sample.xlsx";
FileStream sw = new FileStream(path, FileMode.Open, FileAccess.Read);
IWorkbook workbook = WorkbookFactory.Create(sw);
ISheet sheet = workbook.GetSheetAt(0);
IRow row = sheet.GetRow(12);
ICell cell = row.CreateCell(row.LastCellNum);
cell.SetCellValue("test");
workbook.CreateSheet("Ripon");
sw.Close();
var exportData = new MemoryStream();
workbook.Write(exportData);
exportData.Seek(0, SeekOrigin.Begin);  // reset stream to beginning so it can be read
string saveAsFileName = string.Format("Export-{0:d}.xlsx", DateTime.Now).Replace("/", "-");
return File(exportData, "application/vnd.ms-excel", saveAsFileName);
}

最新更新