从HTTP流式传输时损坏文件

时间:2014-01-24 21:13:01

标签: c# asp.net asp.net-mvc stream npoi

我遇到了通过HTTP响应流式传输文件的问题。无论我做什么,它都会被破坏!

背景是我需要发送生成的XLS文件(我正在使用NPOI)。我知道生成的文件很好,因为如果我用FileStream将它直接保存到磁盘上,我可以打开它并且没有问题!但是......当我尝试通过HTTP流式传输该文件时,它出现了损坏(我尝试了三种不同的方法,如下所示......)。除此之外,它不仅是XLS文件被破坏,而且是我加载的所有文件(我已经尝试过jpg,png和txt文件)。每当我通过HTTP发送它们时,它就会被破坏。不管怎样,这是我尝试过的:

  1. 我尝试过手动构建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;
    
  2. 我尝试过使用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");
    
  3. 我尝试过使用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");
    
  4. 我尝试过使用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");
    
  5. 我尝试加载随机文件,如:

    return File(@"C:\test.jpg", "image/jpeg", "test.jpg");
    
  6. 执行MD5或CRC检查还会向我显示我通过HTTP获取的文件与原始文件不同(即使它们具有完全相同的字节数)。

5 个答案:

答案 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");