asp.net mvc5 下载文件及断点续传下载

常规下载

控制器自带的 FileContentResult 可以让我们很方便的返回文件到服务端,减少了很多步骤。用于下载文件的时候,像视频、文本、图片这种浏览器支持的文件,默认就会被浏览器打开。这时候想让它变成下载,还需要设置一下响应头,告诉浏览器如何处理才行。

         public ActionResult DownLoadFile(String path, string fileName, string contentType)
        {
            Response.AddHeader("Content-Disposition", "attachment; filename=" + Server.UrlEncode(fileName));
            return File(path,contentType);
        }

 以上,在js使用 location.href = fileDownloadUrl 这样简单的方式即可实现在asp.net mvc5下载文件。关键是这个Content-Disposition,它的内容大概就是说明以什么方式处理,默认的文件名是什么。attachment 是以附件方式处理的意思,后面的就是文件名了,url编码处理之后可以避免那些因为带空格的文件名等等带来的问题。

断点续传下载

        public void FileRangeDownload()
        {string fileName = "lubuntu-19.04-desktop-amd64.iso";   //客户端保存的文件名  
            string filePath = Server.MapPath($"./{fileName}");//要被下载的文件路径 

            var range = Request.Headers["Range"]; // Range 一般是"bytes=397506944-"
            if (!string.IsNullOrWhiteSpace(range))//如果遵守协议,支持断点续传
            {
                using (StreamReader reader = new StreamReader(System.IO.File.OpenRead(filePath)))
                {
                    var fileLength = new FileInfo(filePath).Length; //文件的总大小
                    fileLength = reader.BaseStream.Length;
                    long begin; //文件的开始位置
                    long end; //文件的结束位置
                    long.TryParse(range.Split('=')[1].Split('-')[0], out begin);
                    long.TryParse(range.Split('-')[1], out end);
                    end = end - begin > 0 ? end : (fileLength - 1);

                    //表头 表明  下载文件的开始、结束位置 和文件总大小
                    Response.AddHeader("Content-Range", "bytes " + begin + "-" + end + "/" + fileLength);
                    Response.ContentType = "application/octet-stream";
                    Response.AddHeader("Content-Disposition", "attachment;filename=" + fileName);
                    Response.StatusCode = 206;
                    Response.TransmitFile(filePath, begin, (end - begin + 1)); //发送 文件开始位置读取的大小
                }
            }
            else
            {
                Response.ContentType = "application/octet-stream";
                Response.AddHeader("Content-Disposition", "attachment;filename=" + fileName);
                Response.TransmitFile(filePath);
            }
        }

注意点是从请求头读取Range,获得本次请求客户需要下载的区间,如果没有的话就是直接下载,如果有的话注意响应状态修改206,表示返回的内容是部分内容,否则断点续传继续下载可能重新下载。另外Last-Modified、ETag可用来标记资源是否更新,从而决定是否重新下载,这里不做演示。

题外话,这个通过设置响应头来保证文件以附件形式下载的功能早在一年前就用过一次,当时看了一脸懵,也没记下来详细了解,现在又用到了,模模糊糊只记得好像在哪用过一次,当然不记得怎么写了,网上搜,一时又找不到,还是得自己一码一字的敲下来,这样印象深刻而且以后又容易找。什么转载啊,复制粘贴的都是浮云,谁码谁知道!

posted @ 2017-11-30 20:49  笑笑🤞  阅读(3274)  评论(0编辑  收藏  举报