我在MVC4中有一个文件浏览器应用程序,允许您从控制器下载所选文件。
目前,FileResult返回文件的Stream以及其他响应头。虽然这适用于较小的文件,但较大的文件会生成OutOfMemoryException。
我想要做的是从控制器传输文件,而不是以类似于WebForms中的HttpReponse.TransmitFile的方式在内存中缓冲。
如何实现这一目标?
答案 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?),这不是解决方案。
如果您需要其他方法来实现目标,请告诉我有关您的要求的更多信息。