.net Mvc文件下载的功能,大文件下载完成之后修改数据库功能

原文: .net Mvc文件下载的功能,大文件下载完成之后修改数据库功能

我服务器上文件只能下载一次,下载了之后就不能下载了,大文件或网速不好时,可能服务端文件流发送完了,客户端还没下载完,导致下载失败,

那么最好的办法就是:在续传时不判断(If-Range,或If-Match 不为空时不判断,仍然发送对应的文件流)就行了,这样有一个漏洞,就是一个文件没下载完时,可以同时下载很多次,但是没办法,客户使用浏览器下载不好控制(如果记录用户开始下载的次数,逻辑上也不行—他可以下载到一半,然后时间不够不下载了,下次再重新下载,这在业务上也是允许他没下载完时重新下载的)。


        #region 下载文件处理-downfiledeal

        /// <summary>

        /// 下载文件处理

        /// </summary>

        /// <param name="ResourceID">资源id</param>

        /// <param name="UserID">用户id</param>

        /// <param name="downtype">下载类型:1-购买,2-今日免费,3-订阅用户</param>

        /// <param name="webtitle">提示页面titie</param>

        /// <param name="ResourceType">资源类型(暂时不考虑)</param>

        /// <returns></returns>

        private string downfiledeal(string ResourceID, string UserID, string downtype, string webtitle, string ResourceType = "")

        {

            TopicInformationBLL bll_tf = new TopicInformationBLL();

            TopicInformation tf = bll_tf.GetById(ResourceID);

            bll_tf.Dispose();

            string FilePath = "";

            FilePath = tf.TopicSourceFile.ToLower();

            if (FilePath.StartsWith("http://www.***.com"))//不是外网文件夹服务器路径

            {

                FilePath = FilePath.Replace("http://www.***.com", "");

            }

            if (!FilePath.StartsWith("/")) FilePath = "/" + FilePath;

            FilePath = Server.MapPath(FilePath);

            FileInfo DownloadFile = new FileInfo(FilePath);

            System.IO.Stream iStream = null;

            int downsize = 1024;//读取web.config中的配置

            try { downsize = Convert.ToInt32(System.Configuration.ConfigurationManager.AppSettings["downsize"]); }

            catch { downsize = 1024; }

            int buffersize = 1024 * downsize;//默认每次发送1K;

            byte[] buffer = new Byte[buffersize];// Buffer to read 10K bytes in chunk:

            int currentlength;// Length of each read to buffer:

            long dataToRead;// Total bytes to read:

            long dataSended;//已发送的字节

            long datalength;//文件字节总长度

            string filename = System.IO.Path.GetFileName(FilePath); // Identify the file name.

            try

            {

                System.Collections.Specialized.NameValueCollection hds = Request.Headers;

                long startBytes = 0;

                Response.Clear();

                Response.ClearHeaders();

                if (Request.Headers["Range"] != null)

                {//------如果是续传请求,则获取续传的起始位置,即已经下载到客户端的字节数------  

                    Response.StatusCode = 206;//重要:续传必须,表示局部范围响应。初始下载时默认为200  

                    string[] range = Request.Headers["Range"].Split(new char[] { '=', '-' });//"bytes=1474560-"  

                    startBytes = Convert.ToInt64(range[1]);//已经下载的字节数,即本次下载的开始位置    

                    if (startBytes < 0 || startBytes >= DownloadFile.Length)

                    {//无效的起始位置  

                        startBytes = 0;

                    }

                }

                iStream = new System.IO.FileStream(FilePath, System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.Read);// Open the file.

                dataSended = 0;

                datalength =

                dataToRead = iStream.Length - startBytes;// Total bytes to read:

                Response.Buffer = true;

                string lastUpdateTiemStr = System.IO.File.GetLastWriteTimeUtc(FilePath).ToString("r");

                string eTag = HttpUtility.UrlEncode(filename, Encoding.UTF8) + lastUpdateTiemStr;

                Response.AppendHeader("ETag", "\"" + eTag + "\"");//重要:续传必须 

                if (startBytes > 0)

                {

                    if (Request.Headers["If-Range"] != null)//(IE,360)对应响应头ETag:文件名+文件最后修改时间  

                    {

                        //----------上次被请求的日期之后被修改过-------------- 

                        string If_Range = Request.Headers["If-Range"].Replace("\"", "");

                        if (If_Range != eTag)

                        {//文件修改过  

                            Response.StatusCode = 412;//预处理失败  

                            return "文件名验证失败";

                        }

                    }

                    else if (Request.Headers["If-Match"] != null)//(火狐)对应响应头ETag:文件名+文件最后修改时间  

                    {

                        //----------上次被请求的日期之后被修改过--------------  

                        string If_Match = Request.Headers["If-Match"].Replace("\"", "");

                        if (If_Match != eTag)

                        {//文件修改过 

                            Response.StatusCode = 412;//预处理失败  

                            return "文件名验证失败";

                        }

                    }

                    iStream.Seek(startBytes, SeekOrigin.Begin);

                    Response.AddHeader("Content-Range", string.Format(" bytes {0}-{1}/{2}", startBytes, DownloadFile.Length - 1, DownloadFile.Length));

                    Response.AddHeader("Accept-Ranges", "bytes");//重要:续传必须  

                }

                Response.AppendHeader("Content-Length", (DownloadFile.Length - startBytes).ToString());



                Response.ContentType = "application/octet-stream";

                Response.AddHeader("Connection", "Keep-Alive");

                Response.AddHeader("Content-Disposition", "attachment; filename=" + filename);

                while (dataToRead > 0)// Read the bytes.

                {

                    if (Response.IsClientConnected)// Verify that the client is connected.

                    {

                        currentlength = iStream.Read(buffer, 0, buffersize);// Read the data in buffer.

                        Response.OutputStream.Write(buffer, 0, currentlength); // Write the data to the current output stream.

                        //Response.BinaryWrite(buffer);

                        Response.Flush();// Flush the data to the HTML output.

                        //buffer = new Byte[10000];

                        dataToRead = dataToRead - currentlength;

                        dataSended = dataSended + currentlength;

                        Thread.Sleep(1000);//每秒钟发送一次

                    }

                    else

                    {

                        dataToRead = -1;//prevent infinite loop if user disconnects

                    }

                }

                if (dataToRead == 0 && dataSended>0)//发送、下载完成datalength == dataSended

                {

                    //UpdateOrderWhenDownloaded(ResourceID, UserID, downtype);//下载完成,修改数据库状态

                }

                return "";

            }

            catch (Exception ex)

            {

                CommonFun.WritetTxtLog("下载出错:" + ex.Message);

                return CommonFun.GetInformationHtml(webtitle, "下载出错 : " + ex.Message);

            }

            finally

            {



                if (iStream != null)

                {

                    iStream.Close();//Close the file.

                }

            }

        }

        #endregion



        #region 返回显示标题的网页提示文本

        /// <summary>

        /// 返回显示标题的网页提示文本

        /// </summary>

        /// <param name="title">网站title</param>

        /// <param name="body">显示的文字</param>

        /// <returns></returns>

        public static string GetInformationHtml(string title, string body)

        {

            StringBuilder sb = new StringBuilder();

            sb.Append("<html>");

            sb.Append("<head>");

            sb.AppendFormat("<title>{0}</title>",title);

            sb.Append("<style type=\"text/css\">");

            sb.Append(".fixed_div { position:absolute; z-index:2008; bottom:0px; left:0px; width:100%;text-align:center;height:20px; border:0px solid #e5e5e5; background:#e5e5e5; }");

            sb.Append(".margin_auto{margin:-7px auto;width:980px;height:100%;overflow:hidden;}");

            sb.Append(".nounderline{text-decoration:none;}");

            sb.Append(".info{color:red;border:0px solid #e5e5e5; background:#e5e5e5;height:100%;}");

            sb.Append("</style>");

            sb.Append("</head>");

            sb.Append("<body>");

            sb.Append("<div class=\"margin_auto\">");

            sb.Append("<div class=\"info\">");

            sb.Append("<span style=\"font-style:italic;\">提示信息:</span><br/>");

            sb.Append(body);

            sb.Append("</div>");

            sb.Append("<div class=\"fixed_div\">Power By <a href=\"http://www.***.com\" target=\"_blank\" class=\"nounderline\">www.kinpan.com</a><div>");

            sb.Append("</div>");

            sb.Append("</body>");

            sb.Append("</html>");

            return sb.ToString() ;

        }

        #endregion




如果response.writefile,或mvc 中的返回 fileresult,谁知道它下载完成了,这很难控制,现在这样发送,发送完成之后就下载完成了,还能续传,比较精确。。


你可能感兴趣的:(.net)