博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
.net Mvc文件下载的功能,大文件下载完成之后修改数据库功能
阅读量:4688 次
发布时间:2019-06-09

本文共 7649 字,大约阅读时间需要 25 分钟。

原文:

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

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

#region 下载文件处理-downfiledeal        ///         /// 下载文件处理        ///         /// 资源id        /// 用户id        /// 下载类型:1-购买,2-今日免费,3-订阅用户        /// 提示页面titie        /// 资源类型(暂时不考虑)        /// 
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 返回显示标题的网页提示文本 /// /// 返回显示标题的网页提示文本 /// /// 网站title /// 显示的文字 ///
public static string GetInformationHtml(string title, string body) { StringBuilder sb = new StringBuilder(); sb.Append(""); sb.Append(""); sb.AppendFormat("{0}",title); sb.Append(""); sb.Append(""); sb.Append(""); sb.Append("
"); sb.Append("
"); sb.Append("
提示信息:
"); sb.Append(body); sb.Append("
"); sb.Append("
Power By
www.kinpan.com
"); sb.Append("
"); sb.Append(""); sb.Append(""); return sb.ToString() ; } #endregion

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

posted on
2014-02-24 00:55 阅读(
...) 评论(
...)

转载于:https://www.cnblogs.com/lonelyxmas/p/3563938.html

你可能感兴趣的文章