ASP.NET Core下载大文件的实现

原文: ASP.NET Core下载大文件的实现

当咱们的ASP.NET Core网站须要支持下载大文件时,若是不作控制可能会致使用户在访问下载页面时发生无响应,使得浏览器崩溃。能够参考以下代码来避免这个问题。
 
关于此代码的几点说明:
  1. 将数据分红较小的部分,而后将其移动到响应输出流以供下载,从而获取这些数据。
  2. 根据下载的文件类型来指定 Response.ContentType 。(这个网址能够找到大部分文件类型的对照表:http://tool.oschina.net/commons
  3. 在每次调用Response.Body.Write后记得调用 Response.Body.Flush()
  4. 在循环下载的过程当中使用 HttpContext.RequestAborted.IsCancellationRequested 这个判断能够帮助程序尽早发现链接是否正常。若不正常,能够及早放弃下载,以释放所占用的服务器资源。


 
本例使用ASP.NET Core MVC中Controller的Action来演示大文件的下载代码,根据须要也能够改成其它方式(例如ASP.NET Core的中间件)来作下载。
复制代码
using Microsoft.AspNetCore.Mvc; using System.IO; using System.Web; namespace AspNetCoreDownload.Controllers { public class HomeController : Controller { public IActionResult Index() { return View(); } /// <summary>
        /// DownloadBigFile用于下载大文件,循环读取大文件的内容到服务器内存,而后发送给客户端浏览器 /// </summary>
        public IActionResult DownloadBigFile() { var filePath = @"D:\Download\测试文档.xlsx";//要下载的文件地址,这个文件会被分红片断,经过循环逐步读取到ASP.NET Core中,而后发送给客户端浏览器
            var fileName = Path.GetFileName(filePath);//测试文档.xlsx

            int bufferSize = 1024;//这就是ASP.NET Core循环读取下载文件的缓存大小,这里咱们设置为了1024字节,也就是说ASP.NET Core每次会从下载文件中读取1024字节的内容到服务器内存中,而后发送到客户端浏览器,这样避免了一次将整个下载文件都加载到服务器内存中,致使服务器崩溃
 Response.ContentType = "application/vnd.ms-excel";//因为咱们下载的是一个Excel文件,因此设置ContentType为application/vnd.ms-excel

            var contentDisposition = "attachment;" + "filename=" + HttpUtility.UrlEncode(fileName);//在Response的Header中设置下载文件的文件名,这样客户端浏览器才能正确显示下载的文件名,注意这里要用HttpUtility.UrlEncode编码文件名,不然有些浏览器可能会显示乱码文件名
            Response.Headers.Add("Content-Disposition", new string[] { contentDisposition }); //使用FileStream开始循环读取要下载文件的内容
            using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read)) { using (Response.Body)//调用Response.Body.Dispose()并不会关闭客户端浏览器到ASP.NET Core服务器的链接,以后还能够继续往Response.Body中写入数据
 { long contentLength = fs.Length;//获取下载文件的大小
                    Response.ContentLength = contentLength;//在Response的Header中设置下载文件的大小,这样客户端浏览器才能正确显示下载的进度

                    byte[] buffer; long hasRead = 0;//变量hasRead用于记录已经发送了多少字节的数据到客户端浏览器 //若是hasRead小于contentLength,说明下载文件还没读取完毕,继续循环读取下载文件的内容,并发送到客户端浏览器
                    while (hasRead < contentLength) { //HttpContext.RequestAborted.IsCancellationRequested可用于检测客户端浏览器和ASP.NET Core服务器之间的链接状态,若是HttpContext.RequestAborted.IsCancellationRequested返回true,说明客户端浏览器中断了链接
                        if (HttpContext.RequestAborted.IsCancellationRequested) { //若是客户端浏览器中断了到ASP.NET Core服务器的链接,这里应该马上break,取消下载文件的读取和发送,避免服务器耗费资源
                            break; } buffer = new byte[bufferSize]; int currentRead = fs.Read(buffer, 0, bufferSize);//从下载文件中读取bufferSize(1024字节)大小的内容到服务器内存中
 Response.Body.Write(buffer, 0, currentRead);//发送读取的内容数据到客户端浏览器
                        Response.Body.Flush();//注意每次Write后,要及时调用Flush方法,及时释放服务器内存空间
 hasRead += currentRead;//更新已经发送到客户端浏览器的字节数
 } } } return new EmptyResult(); } } }
复制代码
相关文章
相关标签/搜索