7

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

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

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

如何实现?

4

3 回答 3

14

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

Response.BufferOutput = false;
return File(fileStream, contentType);
于 2016-06-11T02:04:44.547 回答
3

是的,您可以使用 Web Api 来流式传输文件,请查看这篇文章在 ASP.NET Web API 中处理大文件

于 2012-10-03T14:02:43.843 回答
0

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

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

    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 阅读器插件时出现一些问题。对于内联参数,您可以使用“false”。

另外,您可以在此代码周围使用 try/catch,因为任何 Response.IsClientConnecter/Write/Flush 都可能在客户端断开连接时引发异常。

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

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

于 2012-10-03T14:30:28.583 回答