プロジェクトで使用されているaspを共有します.Netダウンロード業務のサービス側ベースクラス(クライアントがダウンロードパーセンテージの進捗を表示することをサポートし、同時数制御をサポートし、制限速度をサポートする)

22659 ワード

/// /// :asp.net ( , , ) /// :2015-11-20 /// :pcw ///https://www.cnblogs.com/taohuadaozhu /// : , iis 。 /// public abstract class DownLoadAbs : IHttpHandler { private static StatusDataDict currStatuDataDict = new StatusDataDict(300); protected object lockObj = new object(); public virtual void ProcessRequest(HttpContext context) { string sDiplayFileName = this.GetDisplayFileName(context); string sServerFileFullPath = this.GetServerFileFullPath(context); int iDownload = 0; iDownload = this.ResponseFile(context.Request, context.Response, sDiplayFileName, sServerFileFullPath, this.BytesCountPerSecond); if (iDownload != 1) { Utils.SaveErrorLog(string.Format(" 【{0}】 (2015-12-15v1), ={1}", sServerFileFullPath, iDownload)); if (iDownload == -202) { context.Response.Write(RuntimeContext.GetResponseJson("", -1, null)); } else if (iDownload == -203) { context.Response.Write(RuntimeContext.GetResponseJson("", -2, null)); } context.Response.End(); } } protected abstract string GetDisplayFileName(HttpContext hcontext); protected abstract string GetServerFileFullPath(HttpContext hcontext); protected virtual int GetMaxConnectCount() { return 3; } protected virtual long BytesCountPerSecond { get { return 1024000; } } public bool IsReusable { get { return false; } } /// /// _Request: Page.Request , _Response: Page.Response , _fileName: , _fullPath: , _speed ( :1024000 B, 1M/ ) /// /// /// /// /// /// /// protected int ResponseFile(HttpRequest _Request, HttpResponse _Response, string _displayFileName, string _serverFilefullPath, long _speed) { return this.ResponseForDownloadFile(_Request, _Response, _displayFileName, _serverFilefullPath, _speed); } /// /// _Request: Page.Request , _Response: Page.Response , _fileName: , _fullPath: , _speed ( :1024000 B, 1M/ ) /// /// /// /// /// /// /// protected virtual int ResponseForDownloadFile(HttpRequest _Request, HttpResponse _Response, string _displayFileName, string _serverFilefullPath, long _speed) { bool bSuccess = true; if (string.IsNullOrEmpty(_serverFilefullPath)) return -101; if (string.IsNullOrEmpty(_displayFileName)) return -102; if (_speed < 1) return -103; if (_Request == null) return -104; if (_Response == null) return -105; if (File.Exists(_serverFilefullPath) == false) return -201; if (currStatuDataDict.ExistsStatus(_serverFilefullPath)) { return -202; } if (currStatuDataDict.GetStatusCount() >= this.GetMaxConnectCount()) { return -203; } currStatuDataDict.AddStatusData(_serverFilefullPath); FileStream targetFile = new FileStream(_serverFilefullPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); BinaryReader br = new BinaryReader(targetFile); try { _Response.AddHeader("Accept-Ranges", "bytes"); _Response.Buffer = false; long fileTotalLength = targetFile.Length; long startBytes = 0; int packForBlock = 10240; //10K bytes //int sleep = 200; // 5 5*10K bytes decimal dSleep = Convert.ToDecimal(1000 * packForBlock / _speed); decimal dMaxCount = 0; int sleep = (int)Math.Floor(dSleep) + 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", (fileTotalLength - startBytes).ToString());// if (startBytes != 0)// { _Response.AddHeader("Content-Range", string.Format(" bytes {0}-{1}/{2}", startBytes, fileTotalLength - 1, fileTotalLength));// } /* _Response.AddHeader("Connection", "Keep-Alive"); _Response.AddHeader("Keep-Alive", "timeout=600, max=4"); */ _Response.ContentType = "application/octet-stream"; _Response.AddHeader("Content-Disposition", "attachment;filename=" + HttpUtility.UrlEncode(_displayFileName, System.Text.Encoding.UTF8)); br.BaseStream.Seek(startBytes, SeekOrigin.Begin); dMaxCount = (fileTotalLength - startBytes) / packForBlock; int maxCount = (int)Math.Floor(dMaxCount) + 1; byte[] bytesRead = new byte[packForBlock]; for (int i = 0; i < maxCount; i++) { if (_Response != null && _Response.IsClientConnected) { if (File.Exists(_serverFilefullPath)) { bytesRead = br.ReadBytes(packForBlock); if (bytesRead != null) { _Response.BinaryWrite(bytesRead); //_Response.Flush();//add by pcw Thread.Sleep(sleep);// } } } else { i = maxCount; } } } catch (Exception error) { bSuccess = false; Utils.SaveErrorLog(string .Format(" 【{0}】 :{1}, :{2}", _serverFilefullPath, error.Message, error.StackTrace)); } finally { currStatuDataDict.RemoveStatuData(_serverFilefullPath); if (br != null) { br.Close(); br.Dispose(); br = null; } if (targetFile != null) { targetFile.Close(); targetFile.Dispose(); targetFile = null; } if (_Response != null) { if (bSuccess) { Utils.SaveLog(string.Format(" 【{0}】", _serverFilefullPath)); } //_Response.End(); HttpContext.Current.Response.SuppressContent = true; // Gets or sets a value indicating whether to send HTTP content to the client. HttpContext.Current.ApplicationInstance.CompleteRequest(); // Causes ASP.NET to bypass all events and filtering in the HTTP pipeline chain of execution and directly execute the EndRequest event. } } return 1; } }