asp.net mvc如何实现文件下载

本文介绍了一种在ASP.NET中实现文件下载的方法,包括验证HTTP请求、处理续传请求及设置必要的HTTP响应头等关键步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 public Action LoadFile()
        {
            //   string filePath = Server.MapPath("~") + "upload/wms.txt";
            string filePath = Server.MapPath("~") + "upload/MiSP.rar";
            long speed = 500000;
            DownloadFile(HttpContext, filePath, speed);
            return null;
        }
     
        public static bool DownloadFile(HttpContextBase httpContext, string filePath, long speed)   
        {   
            bool ret = true;   
            try  
            {   
              #region--验证:HttpMethod,请求的文件是否存在   
                switch (httpContext.Request.HttpMethod.ToUpper())   
                { //目前只支持GET和HEAD方法   
                    case "GET":   
                    case "HEAD":   
                        break;   
                    default:   
                        httpContext.Response.StatusCode = 501;   
                        return false;   
                }
                if (!System.IO.File.Exists(filePath))   
                {   
                    httpContext.Response.StatusCode = 404;   
                    return false;   
                }   
                #endregion   
  
               #region 定义局部变量   
                 long startBytes = 0;   
                int packSize = 1024 * 10; //分块读取,每块10K bytes   
                string fileName = Path.GetFileName(filePath);   
                FileStream myFile = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);   
                BinaryReader br = new BinaryReader(myFile);   
                long fileLength = myFile.Length;   
  
                int sleep = (int)Math.Ceiling(1000.0 * packSize / speed);//毫秒数:读取下一数据块的时间间隔   
                string lastUpdateTiemStr = System.IO.File.GetLastWriteTimeUtc(filePath).ToString("r");   
                string eTag = HttpUtility.UrlEncode(fileName, Encoding.UTF8) + lastUpdateTiemStr;//便于恢复下载时提取请求头;   
                #endregion   
  
                #region--验证:文件是否太大,是否是续传,且在上次被请求的日期之后是否被修   
                if (myFile.Length > Int32.MaxValue)   
                {//-------文件太大了-------   
                    httpContext.Response.StatusCode = 413;//请求实体太大   
                    return false;   
                }   
  
                if (httpContext.Request.Headers["If-Range"] != null)//对应响应头ETag:文件名+文件最后修改时间   
                {   
                    //----------上次被请求的日期之后被修改过--------------   
                    if (httpContext.Request.Headers["If-Range"].Replace("\"", "") != eTag)   
                    {//文件修改过   
                        httpContext.Response.StatusCode = 412;//预处理失败   
                        return false;   
                    }   
                }   
                #endregion   
  
                try  
                {   
                 #region -------添加重要响应头、解析请求头、相关验证-------------------   


                    byte[] bytes = new byte[myFile.Length];
                    myFile.Read(bytes, 0, bytes.Length); 
                    httpContext.Response.Clear();   
                    httpContext.Response.Buffer = false;
                    httpContext.Response.AddHeader("Content-MD5", GetMD5Hash(bytes));//用于验证文件   
                    httpContext.Response.AddHeader("Accept-Ranges", "bytes");//重要:续传必须   
                    httpContext.Response.AppendHeader("ETag", "\"" + eTag + "\"");//重要:续传必须   
                    httpContext.Response.AppendHeader("Last-Modified", lastUpdateTiemStr);//把最后修改日期写入响应                   
                    httpContext.Response.ContentType = "application/octet-stream";//MIME类型:匹配任意文件类型   
                    httpContext.Response.AddHeader("Content-Disposition", "attachment;filename=" + HttpUtility.UrlEncode(fileName, Encoding.UTF8).Replace("+", "%20"));   
                    httpContext.Response.AddHeader("Content-Length", (fileLength - startBytes).ToString());   
                    httpContext.Response.AddHeader("Connection", "Keep-Alive");   
                    httpContext.Response.ContentEncoding = Encoding.UTF8;   
                    if (httpContext.Request.Headers["Range"] != null)   
                    {//------如果是续传请求,则获取续传的起始位置,即已经下载到客户端的字节数------   
                        httpContext.Response.StatusCode = 206;//重要:续传必须,表示局部范围响应。初始下载时默认为200   
                        string[] range = httpContext.Request.Headers["Range"].Split(new char[] { '=', '-' });//"bytes=1474560-"   
                        startBytes = Convert.ToInt64(range[1]);//已经下载的字节数,即本次下载的开始位置     
                        if (startBytes < 0 || startBytes >= fileLength)   
                        {//无效的起始位置   
                            return false;   
                        }   
                    }   
                    if (startBytes > 0)   
                    {//------如果是续传请求,告诉客户端本次的开始字节数,总长度,以便客户端将续传数据追加到startBytes位置后----------   
                        httpContext.Response.AddHeader("Content-Range", string.Format(" bytes {0}-{1}/{2}", startBytes, fileLength - 1, fileLength));   
                    }   
                    #endregion   
  
                    #region -------向客户端发送数据块-------------------   
                    br.BaseStream.Seek(startBytes, SeekOrigin.Begin);   
                    int maxCount = (int)Math.Ceiling((fileLength - startBytes + 0.0) / packSize);//分块下载,剩余部分可分成的块数   
                    for (int i = 0; i < maxCount && httpContext.Response.IsClientConnected; i++)   
                    {//客户端中断连接,则暂停   
                        httpContext.Response.BinaryWrite(br.ReadBytes(packSize));   
                        httpContext.Response.Flush();   
                        if (sleep > 1) Thread.Sleep(sleep);   
                    }   
                    #endregion   
                }   
                catch  
                {   
                    ret = false;   
                }   
                finally  
                {   
                    br.Close();   
                    myFile.Close();   
                }   
            }   
            catch  
            {   
                ret = false;   
            }   
            return ret;   
        }




        static string GetMD5Hash(byte[] buffer)
        {
            MD5 md5Hasher = MD5.Create();


            byte[] data = md5Hasher.ComputeHash(buffer);


            StringBuilder sBuilder = new StringBuilder();


            for (int i = 0; i < data.Length; i++)
            {
                sBuilder.Append(data[i].ToString("x2"));
            }
            return sBuilder.ToString();

        }


<html>
    <head>
        
        <meta name="viewport" content="width=device-width" />
        <script src="~/Scripts/jquery-1.8.3.js"></script>
        <title>Error</title>
        <script type="text/javascript">
            $(function() {
                $("#test").click(function() {
                    $("#getExcel").submit();
                });
            });
        </script>
    </head>
    
    <body>
        <div><a href="http://192.168.1.56:8024/Download/loadfile">test</a></div>
         <form id="getExcel" method="get" action="/Download/loadfile">
         <div><button id="test">下载文件</button></div>
          </form>
        <div>
            <img src="/Content/404.jpg"/>
        </div>
    
    </body>
</html>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值