我在 MVC4 中有一个文件浏览器应用程序,它允许您从控制器下载选定的文件。
目前,FileResult 返回文件的 Stream 以及其他响应标头。虽然这适用于较小的文件,但较大的文件会生成 OutOfMemoryException。
我想做的是从控制器传输文件,而不以类似于 WebForms 中的 HttpReponse.TransmitFile 的方式在内存中缓冲。
如何实现?
我在 MVC4 中有一个文件浏览器应用程序,它允许您从控制器下载选定的文件。
目前,FileResult 返回文件的 Stream 以及其他响应标头。虽然这适用于较小的文件,但较大的文件会生成 OutOfMemoryException。
我想做的是从控制器传输文件,而不以类似于 WebForms 中的 HttpReponse.TransmitFile 的方式在内存中缓冲。
如何实现?
您可以在返回文件结果之前禁用响应缓冲区。
Response.BufferOutput = false;
return File(fileStream, contentType);
是的,您可以使用 Web Api 来流式传输文件,请查看这篇文章在 ASP.NET Web API 中处理大文件
除了上面描述配置的链接之外,您还可以使用 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 ?)这不是解决方案。
如果您需要其他方法来实现您的目标,请告诉我有关您的要求的更多信息。