標籤:
轉自:http://www.cnblogs.com/90nice/p/3489287.html
1.因為要下載大檔案 需要斷點續傳,使用多線程 分段下載 效率比較高,節省資源。
發點牢騷:下載可以用多線程,如果是上傳 我覺得沒必要了。如果是普通使用者(adsl) 上傳速度只有50KB/s 據我所知100MB光纖 家庭使用者下載理論值能達到12.5MB/S 但是上傳目前卻只有 256kb/s 這點速度夠幹啥的。希望以後 上傳下載速度能一致。
下面是一個簡單的例子:
服務端:
如果是分段下載 在http Header 標頭檔裡 要有Range ,下面會有 用戶端的例子。
var range = Request.Headers["Range"]; if (null == range) { //正常情況 200 Response.StatusCode = 200; Response.ContentType = "application/x-zip-compressed"; Response.AddHeader("Content-Disposition", "attachment;filename=" + fName); FileStream fs = new FileStream(fUrl, FileMode.Open); long len = fs.Length; fs.Close(); fs.Dispose(); Response.AddHeader("Accept-Ranges", len.ToString()); Response.TransmitFile(fUrl); } else { //Accept - Range 情況string[] re = range.Split(‘=‘); string[] r = re[1].Split(‘-‘); long start = 0; long alength = 0; long fslength = 0; // 如果開始為空白 從0開始取if (string.IsNullOrEmpty(r[0])) start = 0; else start = Convert.ToInt64(r[0]); //取檔案總長度FileStream fs = new FileStream(fUrl, FileMode.Open); fslength = fs.Length; fs.Close(); fs.Dispose(); // 位元組長度 if (string.IsNullOrEmpty(r[1])) alength = fslength - start; else alength = Convert.ToInt64(r[1]) - start; Response.StatusCode = 206; //分段下載狀態Response.ContentType = "application/x-zip-compressed"; Response.AddHeader("Content-Disposition", "attachment;filename=" + fName); Response.AddHeader("Accept-Ranges", (alength - start).ToString()); Response.AddHeader("Content-Range", "bytes " + start + "-" + (start + alength) + "/" + fslength.ToString()); //Content-Range: bytes 100-200/1024 告訴用戶端 本次請求的檔案位置和總檔案大小// 檔案路徑 開始位置 取多少位元組Response.TransmitFile(fUrl, start, alength);
用戶端 例子:
建立一個 http請求 並 寫入請求的檔案段
var request = (HttpWebRequest)WebRequest.Create("http://localhost:40337/PublicPage/ZrqPublicImg.zip"); request.AddRange(0, 500); try { //擷取HTTP回應,注意HttpWebResponse繼承自IDisposable using (var response = (HttpWebResponse)request.GetResponse()) { if (response.StatusCode == HttpStatusCode.OK) throw new Exception("檔案不支援Range部分下載"); //設定接收資訊的緩衝器var bytes = new byte[5000]; //擷取回應的Stream(位元組流)using (var stream = response.GetResponseStream()) {//FileMode.Append 我這裡是從檔案末尾處寫入 如果是多線程 就要根據具體的請求的位置 寫入檔案using (var outStream = new FileStream(@"D:\222.jpg", FileMode.Append, FileAccess.Write, FileShare.None)) { const int bufferLen = 4096; byte[] buffer = new byte[bufferLen]; int count = 0;while ((count = stream.Read(buffer, 0, bufferLen)) > 0) { outStream.Write(buffer, 0, count); } outStream.Close(); stream.Close(); } } } } catch (Exception ex) { Console.WriteLine("錯誤資訊:{0}", ex.Message); }
以下摘自:http://www.sufeinet.com/forum.php?mod=viewthread&tid=2258&extra=page%3D1%26filter%3Dtypeid%26typeid%3D284%26typeid%3D284
另附支援限速下載的方法(伺服器代碼):
/// <summary> /// 輸出硬碟檔案,提供下載 支援大檔案、續傳、速度限制、資源佔用小 /// </summary> /// <param name="_Request">;Page.Request對象</param> /// <param name="_Response">;Page.Response對象</param> /// <param name="_fileName">下載檔案名稱</param> /// <param name="_fullPath">帶檔案名稱下載路徑</param> /// <param name="_speed">每秒允許下載的位元組數</param> /// <returns>返回是否成功</returns> //--------------------------------------------------------------------- //調用: // string FullPath=Server.MapPath("count.txt"); // ResponseFile(this.Request,this.Response,"count.txt",FullPath,100); //--------------------------------------------------------------------- public static bool ResponseFile(HttpRequest _Request, HttpResponse _Response, string _fileName, string _fullPath, long _speed) { try { FileStream myFile = new FileStream(_fullPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); BinaryReader br = new BinaryReader(myFile); try { _Response.AddHeader("Accept-Ranges", "bytes"); _Response.Buffer = false; long fileLength = myFile.Length; long startBytes = 0; int pack = 10240; //10K bytes int sleep = (int)Math.Floor((double)(1000 * pack / _speed)) + 1; if (_Request.Headers["Range"] != null) { _Response.StatusCode = 206; string[] range = _Request.Headers["Range"].Split(new char[] { ‘=‘, ‘-‘ }); startBytes = Convert.ToInt64(range[1]); } _Response.AddHeader("Content-Length", (fileLength - startBytes).ToString()); if (startBytes != 0) { _Response.AddHeader("Content-Range", string.Format(" bytes {0}-{1}/{2}", startBytes, fileLength - 1, fileLength)); } _Response.AddHeader("Connection", "Keep-Alive"); _Response.ContentType = "application/octet-stream"; _Response.AddHeader("Content-Disposition", "attachment;filename=" + HttpUtility.UrlEncode(_fileName, System.Text.Encoding.UTF8)); br.BaseStream.Seek(startBytes, SeekOrigin.Begin); int maxCount = (int)Math.Floor((double)((fileLength - startBytes) / pack)) + 1; for (int i = 0; i < maxCount; i++) { if (_Response.IsClientConnected) { _Response.BinaryWrite(br.ReadBytes(pack)); Thread.Sleep(sleep); } else { i = maxCount; } } } catch { return false; } finally { br.Close(); myFile.Close(); } } catch { return false; } return true; } }
asp.net c# 斷點續傳 下載 Accept-Ranges