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

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

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

  1. #region 下载文件处理-downfiledeal
  2. /// <summary>
  3. /// 下载文件处理
  4. /// </summary>
  5. /// <param name="ResourceID">资源id</param>
  6. /// <param name="UserID">用户id</param>
  7. /// <param name="downtype">下载类型:1-购买,2-今日免费,3-订阅用户</param>
  8. /// <param name="webtitle">提示页面titie</param>
  9. /// <param name="ResourceType">资源类型(暂时不考虑)</param>
  10. /// <returns></returns>
  11. private string downfiledeal(string ResourceID, string UserID, string downtype, string webtitle, string ResourceType = "")
  12. {
  13. TopicInformationBLL bll_tf = new TopicInformationBLL();
  14. TopicInformation tf = bll_tf.GetById(ResourceID);
  15. bll_tf.Dispose();
  16. string FilePath = "";
  17. FilePath = tf.TopicSourceFile.ToLower();
  18. if (FilePath.StartsWith("http://www.***.com"))//不是外网文件夹服务器路径
  19. {
  20. FilePath = FilePath.Replace("http://www.***.com", "");
  21. }
  22. if (!FilePath.StartsWith("/")) FilePath = "/" + FilePath;
  23. FilePath = Server.MapPath(FilePath);
  24. FileInfo DownloadFile = new FileInfo(FilePath);
  25. System.IO.Stream iStream = null;
  26. int downsize = 1024;//读取web.config中的配置
  27. try { downsize = Convert.ToInt32(System.Configuration.ConfigurationManager.AppSettings["downsize"]); }
  28. catch { downsize = 1024; }
  29. int buffersize = 1024 * downsize;//默认每次发送1K;
  30. byte[] buffer = new Byte[buffersize];// Buffer to read 10K bytes in chunk:
  31. int currentlength;// Length of each read to buffer:
  32. long dataToRead;// Total bytes to read:
  33. long dataSended;//已发送的字节
  34. long datalength;//文件字节总长度
  35. string filename = System.IO.Path.GetFileName(FilePath); // Identify the file name.
  36. try
  37. {
  38. System.Collections.Specialized.NameValueCollection hds = Request.Headers;
  39. long startBytes = 0;
  40. Response.Clear();
  41. Response.ClearHeaders();
  42. if (Request.Headers["Range"] != null)
  43. {//------如果是续传请求,则获取续传的起始位置,即已经下载到客户端的字节数------
  44. Response.StatusCode = 206;//重要:续传必须,表示局部范围响应。初始下载时默认为200
  45. string[] range = Request.Headers["Range"].Split(new char[] { '=', '-' });//"bytes=1474560-"
  46. startBytes = Convert.ToInt64(range[1]);//已经下载的字节数,即本次下载的开始位置
  47. if (startBytes < 0 || startBytes >= DownloadFile.Length)
  48. {//无效的起始位置
  49. startBytes = 0;
  50. }
  51. }
  52. iStream = new System.IO.FileStream(FilePath, System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.Read);// Open the file.
  53. dataSended = 0;
  54. datalength =
  55. dataToRead = iStream.Length - startBytes;// Total bytes to read:
  56. Response.Buffer = true;
  57. string lastUpdateTiemStr = System.IO.File.GetLastWriteTimeUtc(FilePath).ToString("r");
  58. string eTag = HttpUtility.UrlEncode(filename, Encoding.UTF8) + lastUpdateTiemStr;
  59. Response.AppendHeader("ETag", "\"" + eTag + "\"");//重要:续传必须
  60. if (startBytes > 0)
  61. {
  62. if (Request.Headers["If-Range"] != null)//(IE,360)对应响应头ETag:文件名+文件最后修改时间
  63. {
  64. //----------上次被请求的日期之后被修改过--------------
  65. string If_Range = Request.Headers["If-Range"].Replace("\"", "");
  66. if (If_Range != eTag)
  67. {//文件修改过
  68. Response.StatusCode = 412;//预处理失败
  69. return "文件名验证失败";
  70. }
  71. }
  72. else if (Request.Headers["If-Match"] != null)//(火狐)对应响应头ETag:文件名+文件最后修改时间
  73. {
  74. //----------上次被请求的日期之后被修改过--------------
  75. string If_Match = Request.Headers["If-Match"].Replace("\"", "");
  76. if (If_Match != eTag)
  77. {//文件修改过
  78. Response.StatusCode = 412;//预处理失败
  79. return "文件名验证失败";
  80. }
  81. }
  82. iStream.Seek(startBytes, SeekOrigin.Begin);
  83. Response.AddHeader("Content-Range", string.Format(" bytes {0}-{1}/{2}", startBytes, DownloadFile.Length - 1, DownloadFile.Length));
  84. Response.AddHeader("Accept-Ranges", "bytes");//重要:续传必须
  85. }
  86. Response.AppendHeader("Content-Length", (DownloadFile.Length - startBytes).ToString());
  87.  
  88. Response.ContentType = "application/octet-stream";
  89. Response.AddHeader("Connection", "Keep-Alive");
  90. Response.AddHeader("Content-Disposition", "attachment; filename=" + filename);
  91. while (dataToRead > 0)// Read the bytes.
  92. {
  93. if (Response.IsClientConnected)// Verify that the client is connected.
  94. {
  95. currentlength = iStream.Read(buffer, 0, buffersize);// Read the data in buffer.
  96. Response.OutputStream.Write(buffer, 0, currentlength); // Write the data to the current output stream.
  97. //Response.BinaryWrite(buffer);
  98. Response.Flush();// Flush the data to the HTML output.
  99. //buffer = new Byte[10000];
  100. dataToRead = dataToRead - currentlength;
  101. dataSended = dataSended + currentlength;
  102. Thread.Sleep(1000);//每秒钟发送一次
  103. }
  104. else
  105. {
  106. dataToRead = -1;//prevent infinite loop if user disconnects
  107. }
  108. }
  109. if (dataToRead == 0 && dataSended>0)//发送、下载完成datalength == dataSended
  110. {
  111. //UpdateOrderWhenDownloaded(ResourceID, UserID, downtype);//下载完成,修改数据库状态
  112. }
  113. return "";
  114. }
  115. catch (Exception ex)
  116. {
  117. CommonFun.WritetTxtLog("下载出错:" + ex.Message);
  118. return CommonFun.GetInformationHtml(webtitle, "下载出错 : " + ex.Message);
  119. }
  120. finally
  121. {
  122.  
  123. if (iStream != null)
  124. {
  125. iStream.Close();//Close the file.
  126. }
  127. }
  128. }
  129. #endregion
  130.  
  131. #region 返回显示标题的网页提示文本
  132. /// <summary>
  133. /// 返回显示标题的网页提示文本
  134. /// </summary>
  135. /// <param name="title">网站title</param>
  136. /// <param name="body">显示的文字</param>
  137. /// <returns></returns>
  138. public static string GetInformationHtml(string title, string body)
  139. {
  140. StringBuilder sb = new StringBuilder();
  141. sb.Append("<html>");
  142. sb.Append("<head>");
  143. sb.AppendFormat("<title>{0}</title>",title);
  144. sb.Append("<style type=\"text/css\">");
  145. 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; }");
  146. sb.Append(".margin_auto{margin:-7px auto;width:980px;height:100%;overflow:hidden;}");
  147. sb.Append(".nounderline{text-decoration:none;}");
  148. sb.Append(".info{color:red;border:0px solid #e5e5e5; background:#e5e5e5;height:100%;}");
  149. sb.Append("</style>");
  150. sb.Append("</head>");
  151. sb.Append("<body>");
  152. sb.Append("<div class=\"margin_auto\">");
  153. sb.Append("<div class=\"info\">");
  154. sb.Append("<span style=\"font-style:italic;\">提示信息:</span><br/>");
  155. sb.Append(body);
  156. sb.Append("</div>");
  157. sb.Append("<div class=\"fixed_div\">Power By <a href=\"http://www.***.com\" target=\"_blank\" class=\"nounderline\">www.kinpan.com</a><div>");
  158. sb.Append("</div>");
  159. sb.Append("</body>");
  160. sb.Append("</html>");
  161. return sb.ToString() ;
  162. }
  163. #endregion

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

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

  1. notepad++ 文本替换功能,解决excel批量修改数据库的数据操作

    ^ \(' 开始\t ',' 制表符$ '\) 行末 复制出来之后,使用文本替换功能,转换为SQL,添加到临时表中.然后多表关联修改. SELECT COUNT(*) FROM orderno; # ...

  2. MVC&WebForm对照学习:文件下载

    说完了WebForm和MVC中的文件上传,就不得不说用户从服务器端下载资源了.那么今天就扯扯在WebForm和MVC中是如何实现文件下载的.说起WebForm中的文件上传,codeshark在他的博文 ...

  3. ASP.NET 大文件下载的实现思路及代码

    文件下载是一个网站最基本的功能,ASP.NET网站的文件下载功能实现也很简单,但是如果遇到大文件的下载而不做特殊处理的话,那将会出现不可预料的后果.本文就基于ASP.NET提供大文件下载的实现思路及代 ...

  4. 使用Nginx的X-Accel-Redirect实现大文件下载

    在实现文件下载功能时通常有以下几种方式: 1.直接给出下载地址,例如http://****.com/test/test.rar,这种是最直接的方式,任何人都可以下载,无法控制用户的权限. 2.验证权限 ...

  5. 2016 - 1- 24 大文件下载 关于NSOutStream 的使用补充

    // // ViewController.m // 大文件下载 // // Created by Mac on 16/1/24. // Copyright © 2016年 Mac. All right ...

  6. Django 大文件下载

    django提供文件下载时,若果文件较小,解决办法是先将要传送的内容全生成在内存中,然后再一次性传入Response对象中: def simple_file_download(request): # ...

  7. 网络编程---(数据请求+slider)将网络上的大文件下载到本地,并打印其进度

    网络编程---将网络上的大文件下载到本地,并打印其进度. 点击"開始传输"button.将网络上的大文件先下载下来,下载完毕后,保存到本地. UI效果图例如以下: watermar ...

  8. OC - 16.大文件下载

    大文件下载注意事项 若不对下载的文件进行转存,会造成内存消耗急剧升高,甚至耗尽内存资源,造成程序终止. 在文件下载过程中通常会出现中途停止的状况,若不做处理,就要重新开始下载,浪费流量. 大文件下载的 ...

  9. iOS开发-大文件下载与断点下载思路

    大文件下载方案一:利用NSURLConnection和它的代理方法,及NSFileHandle(iOS9后不建议使用)相关变量: @property (nonatomic,strong) NSFile ...

随机推荐

  1. linux下tomcat shutdown后 java进程依然存在

    今天遇到一个非常奇怪的问题,如标题所看到的: linux下(之所以强调linux下,是由于在windows下正常),运行tomcat ./shutdown.sh 后,尽管tomcat服务不能正常訪问了 ...

  2. memset,memcpy,memmove,strcpy,strcat,strcmp的实现(其实很简单,每个程序都只有几行代码)

    面试中的几个小问题 1.对stl中list封装(参考1): 2.对重要C函数实现(参考2): //memset void *memset(void *buffer, int c, int count) ...

  3. 将网站部署到服务器上出现_STORAGE_WRITE_ERROR_问题

    用的thinkphp3.2的框架,在本地运行没有问题,部署到服务器上(基于centos的LAMP环境)即报错,报错信息如下(完全看不懂...):求大神帮帮忙~~~~(>_<)~~~~ :( ...

  4. MapReduce/Hbase进阶提升(原理剖析、实战演练)

    什么是MapReduce? MapReduce是一种编程模型,用于大规模数据集(大于1TB)的并行运算.概念"Map(映射)"和"Reduce(归约)",和他们 ...

  5. 设计模式六大原则(2):里氏替换原则(Liskov Substitution Principle)

    肯定有不少人跟我刚看到这项原则的时候一样,对这个原则的名字充满疑惑.事实上原因就是这项原则最早是在1988年,由麻省理工学院的一位姓里的女士(Barbara Liskov)提出来的. 定义1:假设对每 ...

  6. Stripe

    Description Once Bob took a paper stripe of n squares (the height of the stripe is 1 square). In eac ...

  7. 采用管道处理HTTP请求

    采用管道处理HTTP请求 之所以称ASP.NET Core是一个Web开发平台,源于它具有一个极具扩展性的请求处理管道,我们可以通过这个管道的定制来满足各种场景下的HTTP处理需求.ASP. NET ...

  8. 【转】有效修改max open files/ulimit -n

    [转]有效修改max open files/ulimit -n_追梦20121222_新浪博客     [转]有效修改max open files/ulimit -n    (2011-11-18 0 ...

  9. 菜鸟版JAVA设计模式—从买房子看代理模式

    今天学习了代理模式. 相对于适配器模式,或者说装饰器模式,代理模式理解起来更加简单. 代理这个词应该比較好理解,取代去做就是代理. 比方,我们买卖房子,那么我们会找中介,我要卖房子,可是我们没有时间去 ...

  10. CImageList用法介绍

    图像列表控制(CImageList)是相同大小图像的一个集合,每个集合中均以0为图像的索引序号基数,图像列表通常由大图标或位图构成,其中包含透明位图模式.可以利用WINDOWS32位应用程序接口函数A ...