我在通过HTTP响应中流式传输文件有问题。无论我做什么,它都会破坏!
背景是我需要发送生成的XLS文件(我正在使用NPOI)。我知道生成的文件很好,因为如果我将其直接保存到磁盘上,我可以打开它,没有问题!但是……当我尝试通过HTTP流式传输该文件时,它会损坏(我尝试了三种不同的方法,如下所示……)。为此,最重要的是,不仅XLS文件损坏了,而且是我加载的所有文件(我尝试过JPG,PNG和TXT文件)。每当我通过http发送它们时,它都会损坏。无论如何,这都是我尝试的:
-
我已经尝试手动构建HTTP响应:
Export export = new Export(header, data); MemoryStream stream = export.GetXLSStream("test"); // This generates a memory stream of the XLS file // Writing that stream to a file works! This file opens just fine var fs = new FileStream(@"C:export.xls", FileMode.Create, System.IO.FileAccess.Write); stream.WriteTo(fs); // However, this doesn't! Response.ClearContent(); Response.AddHeader("Cache-Control", "must-revalidate, post-check=0, pre-check=0"); Response.AddHeader("Content-Disposition", "attachment; filename=export.xls"); Response.AddHeader("Content-Type", "application/vnd.ms-excel"); Response.AddHeader("Content-Transfer-Encoding", "binary"); Response.BinaryWrite(stream.ToArray()); Response.End(); return null;
-
我尝试使用FileStreamResult:
Export export = new Export(header, data); MemoryStream stream = export.GetXLSStream("test"); // This generates a memory stream of the XLS file return File(stream, "application/vnd.ms-excel", "export.xsl");
-
我尝试使用FileContentResult:
Export export = new Export(header, data); MemoryStream stream = export.GetXLSStream("test"); // This generates a memory stream of the XLS file return File(stream.ToArray(), "application/vnd.ms-excel", "export.xsl");
-
我尝试使用filepathresult:
Export export = new Export(header, data); MemoryStream stream = export.GetXLSStream("test"); // This generates a memory stream of the XLS file var fs = new FileStream(@"C:export.xls", FileMode.Create, System.IO.FileAccess.Write); stream.WriteTo(fs); fs.Close(); return File(@"C:export.xls", "application/vnd.ms-excel", "export.xsl");
-
,我尝试加载随机文件,例如:
return File(@"C:test.jpg", "image/jpeg", "test.jpg");
进行MD5或CRC检查还向我表明,我通过HTTP获得的文件与原始文件不同(即使它们具有完全相同的字节数)。
这是对我有用的代码:
public MyController : Controller {
public ActionResult GetFile()
{
// ...
return File(stream, "application/octet-stream", "file.xls");
}
}
我在 mvc 中使用 npoi 1.2.5,.net 4.0 按以下方式:
我有自定义ActionResult 类带有以下方法:
public override sealed void ExecuteResult(ControllerContext context)
{
IWorkbook workbook = XlsData.CreateTestWorkbook().Workbook;
HttpResponseBase response = context.HttpContext.Response;
response.Clear();
response.ContentType = "application/vnd.ms-excel";
response.Headers.Add("content-disposition", "attachment; filename=Test.xls");
using (var ms = new MemoryStream())
{
workbook.Write(ms);
ms.WriteTo(response.OutputStream);
}
response.End();
}
其中XlsData.CreateTestWorkbook()
是一些创建我NPOI示例工作簿的类。
然后在我的控制器方法中,我只返回我的自定义ActionResult
我的控制器方法具有 [httpget] 属性,并从
中调用客户端带有HTML链接下载按钮。
看起来它是我在控制器根部应用的空间滤波器,以使输出所有一条线。除了HTML响应外,它都不应该应用于任何其他内容,但是我更改了代码,以使其根本不以此为响应。
尝试此方法,对我来说很好
using (var fileData = new FileStream(filename, FileMode.Create))
{
workbook.Write(fileData);
}
using (var exportData = new MemoryStream())
{
workbook.Write(exportData);
string saveAsFileName = string.Format("MembershipExport-{0:d}.xls", DateTime.Now).Replace("/", "-");
Response.ContentType = "application/vnd.ms-excel";
Response.AddHeader("Content-Disposition", string.Format("attachment;filename={0}", saveAsFileName));
Response.Clear();
Response.BinaryWrite(exportData.GetBuffer());
Response.End();
}
MemoryStream outStream = (MemoryStream)generateFilte.Generate();
outStream.Flush(); //Always catches me out
outStream.Position = 0;
return new FileStreamResult(outStream, "application/vnd.ms-excel");