mvc系列之mvc实现大文件下载
在做项目的过程中有时候会遇到“下载几十M甚至过百M的文件”这样的需求,这时候如果还是用老方法直接将文件一次性读取出来然后写入到响应流,这肯定是不行的,不说别的,光是内存的消耗就可能让服务器垮掉。那么有没有更好的方式呢,答案是肯定的,下面分享一种使用Response.OutputStream实现大文件下载的方式。
首先,自定义一个ActionResult,代码如下:
/// <summary> /// 该类继承了ActionResult,通过重写ExecuteResult方法,进行文件的下载 /// </summary> public class FileResult : ActionResult { private readonly string _filePath;//文件路径 private readonly string _fileName;//文件名称 public FileResult(string filePath,string fileName) { _filePath = filePath; _fileName = fileName; } public override void ExecuteResult(ControllerContext context) { string fileName = _fileName; HttpResponseBase response = context.HttpContext.Response; if (File.Exists(_filePath)) { FileStream fs = null; byte[] fileBuffer = new byte[1024];//每次读取1024字节大小的数据 try { using (fs = File.OpenRead(_filePath)) { long totalLength = fs.Length; response.ContentType = "application/octet-stream"; response.AddHeader("Content-Disposition", "attachment; filename=" + HttpUtility.UrlEncode(fileName)); while (totalLength > 0 && response.IsClientConnected)//持续传输文件 { int length = fs.Read(fileBuffer, 0, fileBuffer.Length);//每次读取1024个字节长度的内容 fs.Flush(); response.OutputStream.Write(fileBuffer, 0, length);//写入到响应的输出流 response.Flush();//刷新响应 totalLength = totalLength - length; } response.Close();//文件传输完毕,关闭相应流 } } catch (Exception ex) { response.Write(ex.Message); } finally { if (fs != null) fs.Close();//最后记得关闭文件流 } } } }
然后在Action里面直接返回一个FileResult的实例即可
public class FileController : Controller { public ActionResult Index() { return View("~/Views/File/Index.cshtml"); } // // GET: /File/ public ActionResult Download() { string filePath = Server.MapPath("~/App_Data/ASP.NETWebAPI2框架揭秘.pdf"); string fileName = "ASP.NETWebAPI2框架揭秘.pdf"; return new FileResult(filePath, fileName); } }
这里,我用了一个47.5MB大小的pdf文件做测试,效果还是不错的。