我遇到了通过HTTP响应流式传输文件的问题。无论我做什么,它都会被破坏!
背景是我需要发送生成的XLS文件(我正在使用NPOI)。我知道生成的文件很好,因为如果我用FileStream将它直接保存到磁盘上,我可以打开它并且没有问题!但是......当我尝试通过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获取的文件与原始文件不同(即使它们具有完全相同的字节数)。
答案 0 :(得分:0)
以下是适用于我的代码:
public MyController : Controller {
public ActionResult GetFile()
{
// ...
return File(stream, "application/octet-stream", "file.xls");
}
}
答案 1 :(得分:0)
我在 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样本工作簿的类。
然后在我的Controller方法中,我只返回自定义的ActionResult
我的控制器方法有一个 [HttpGet] 属性,从中调用 客户端带有html链接下载按钮。
答案 2 :(得分:0)
看起来它是我在控制器根目录下应用的空白过滤器,使输出全部为单行。除了html响应之外,它不应该应用于任何其他内容,但是我已经更改了代码,因此它不会像这样响应。
答案 3 :(得分:0)
尝试这种方法,它适用于我
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();
}
答案 4 :(得分:-1)
MemoryStream outStream = (MemoryStream)generateFilte.Generate();
outStream.Flush(); //Always catches me out
outStream.Position = 0;
return new FileStreamResult(outStream, "application/vnd.ms-excel");