ASP.NET MVC:从FileResult返回大量数据

时间:2012-10-03 13:53:35

标签: asp.net asp.net-mvc controller out-of-memory

我在MVC4中有一个文件浏览器应用程序,允许您从控制器下载所选文件。

目前,FileResult返回文件的Stream以及其他响应头。虽然这适用于较小的文件,但较大的文件会生成OutOfMemoryException。

我想要做的是从控制器传输文件,而不是以类似于WebForms中的HttpReponse.TransmitFile的方式在内存中缓冲。

如何实现这一目标?

3 个答案:

答案 0 :(得分:11)

您可以在返回文件结果之前禁用响应缓冲区。

Response.BufferOutput = false;
return File(fileStream, contentType);

答案 1 :(得分:2)

是的,您可以使用Web Api来流式传输文件,请查看本文Dealing with large files in ASP.NET Web API

答案 2 :(得分:0)

除了上述描述配置的链接外,您还可以使用TransmitFile来“流式传输”文件。但是,TransmitFile在一些http客户端上有一些倒退。

这是我将文件“流”到客户端的代码,作为TransmitFile的替代方案。请注意,我有一个使用WriteFile回滚的配置常量(与你的OutFf问题相同):

    private void RenderContent(string contentType,string fileName, bool inline);

方法代码:

FileInfo fi = new FileInfo(fileName);

Response.ClearHeaders();
Response.ClearContent();

Response.ContentType = contentType;
Response.CacheControl = "No-cache";
Response.Cache.SetCacheability(System.Web.HttpCacheability.NoCache);
Response.AddHeader("Content-Length", fi.Length.ToString());
Response.AddHeader("Content-Disposition", (inline ? "inline" : "attachment") + "; filename=\"" + fi.Name + "\"");

if (cAppInfos.Constant["FallBackToWriteFile"] != null && cAppInfos.Constant["FallBackToWriteFile"] == "true")
{
    Response.WriteFile(fileName);
}
else
{
    int chunkSize = 8192;
    byte[] buffer = new byte[chunkSize];
    int offset = 0;
    int read = 0;
    using (FileStream fs = File.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
    {
        while ((read = fs.Read(buffer, offset, chunkSize)) > 0)
        {
            if (!Response.IsClientConnected)
                break;

            Response.OutputStream.Write(buffer, 0, read);
            Response.Flush();
        }
    }
}

我使用此代码来避免将pdf文件流式传输到旧的acrobat reader插件时出现问题。对于内联参数,您可以使用“false”。

另外,你可以在这段代码中使用try / catch,因为如果客户端断开连接,任何Response.IsClientConnecter / Write / Flush都会抛出异常。

但是,我没有使用MVC,我不确定这个技术是否可以接受,就好像你没有使用过TransmitFile一样,你可能会遇到与此代码相同的问题。 如果你试图将文件嵌入到网页元素中(可能是base64?),这不是解决方案。

如果您需要其他方法来实现目标,请告诉我有关您的要求的更多信息。