From 7b45274cad5195bafb4878f1f887a68a05b2165b Mon Sep 17 00:00:00 2001 From: leiurayer <1432593898@qq.com> Date: Fri, 6 Jan 2023 15:33:06 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E5=A4=9A=E7=BA=BF=E7=A8=8B?= =?UTF-8?q?=E4=B8=8B=E8=BD=BD=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Downloader/MultiThreadDownloader.cs | 125 +++++++++--------- .../Downloader/PartialDownloader.cs | 23 ++-- src/DownKyi.Core/Logging/LogManager.cs | 11 +- .../Download/BuiltinDownloadService.cs | 2 +- 4 files changed, 84 insertions(+), 77 deletions(-) diff --git a/src/DownKyi.Core/Downloader/MultiThreadDownloader.cs b/src/DownKyi.Core/Downloader/MultiThreadDownloader.cs index 84490f7..2c142b3 100644 --- a/src/DownKyi.Core/Downloader/MultiThreadDownloader.cs +++ b/src/DownKyi.Core/Downloader/MultiThreadDownloader.cs @@ -27,7 +27,8 @@ namespace DownKyi.Core.Downloader private bool _rangeAllowed; private readonly HttpWebRequest _request; private Action _requestConfigure = req => req.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.122 Safari/537.36"; - #endregion + + #endregion 属性 #region 公共属性 @@ -68,11 +69,13 @@ namespace DownKyi.Core.Downloader { try { - return PartialDownloaderList.Where(t => t != null).Sum(t => t.TotalBytesRead); + lock (this) + { + return PartialDownloaderList.Where(t => t != null).Sum(t => t.TotalBytesRead); + } } - catch (Exception e) + catch { - Logging.LogManager.Error(e); return 0; } } @@ -91,7 +94,16 @@ namespace DownKyi.Core.Downloader /// /// 下载速度 /// - public float TotalSpeedInBytes => PartialDownloaderList.Sum(t => t.SpeedInBytes); + public float TotalSpeedInBytes + { + get + { + lock (this) + { + return PartialDownloaderList.Sum(t => t.SpeedInBytes); + } + } + } /// /// 下载块 @@ -103,7 +115,7 @@ namespace DownKyi.Core.Downloader /// public string FilePath { get; set; } - #endregion + #endregion 公共属性 #region 变量 @@ -124,7 +136,7 @@ namespace DownKyi.Core.Downloader private readonly AsyncOperation _aop; - #endregion + #endregion 变量 #region 下载管理器 @@ -166,7 +178,7 @@ namespace DownKyi.Core.Downloader { } - #endregion + #endregion 下载管理器 #region 事件 @@ -181,16 +193,16 @@ namespace DownKyi.Core.Downloader return; } - PartialDownloaderList.Sort((x, y) => y.RemainingBytes - x.RemainingBytes); - int rem = PartialDownloaderList[0].RemainingBytes; + PartialDownloaderList.Sort((x, y) => (int)(y.RemainingBytes - x.RemainingBytes)); + var rem = PartialDownloaderList[0].RemainingBytes; if (rem < 50 * 1024) { WaitOrResumeAll(PartialDownloaderList, false); return; } - int from = PartialDownloaderList[0].CurrentPosition + rem / 2; - int to = PartialDownloaderList[0].To; + var from = PartialDownloaderList[0].CurrentPosition + rem / 2; + var to = PartialDownloaderList[0].To; if (from > to) { WaitOrResumeAll(PartialDownloaderList, false); @@ -202,16 +214,19 @@ namespace DownKyi.Core.Downloader var temp = new PartialDownloader(_url, TempFileDirectory, Guid.NewGuid().ToString(), from, to, true); temp.DownloadPartCompleted += temp_DownloadPartCompleted; temp.DownloadPartProgressChanged += temp_DownloadPartProgressChanged; - PartialDownloaderList.Add(temp); + lock (this) + { + PartialDownloaderList.Add(temp); + } temp.Start(_requestConfigure); } - void temp_DownloadPartProgressChanged(object sender, EventArgs e) + private void temp_DownloadPartProgressChanged(object sender, EventArgs e) { UpdateProgress(); } - void UpdateProgress() + private void UpdateProgress() { int pr = (int)(TotalBytesReceived * 1d / Size * 100); if (TotalProgress != pr) @@ -224,11 +239,11 @@ namespace DownKyi.Core.Downloader } } - #endregion + #endregion 事件 #region 方法 - void CreateFirstPartitions() + private void CreateFirstPartitions() { Size = GetContentLength(ref _rangeAllowed, ref _url); int maximumPart = (int)(Size / (25 * 1024)); @@ -247,17 +262,21 @@ namespace DownKyi.Core.Downloader var temp = CreateNew(i, NumberOfParts, Size); temp.DownloadPartProgressChanged += temp_DownloadPartProgressChanged; temp.DownloadPartCompleted += temp_DownloadPartCompleted; - PartialDownloaderList.Add(temp); + lock (this) + { + PartialDownloaderList.Add(temp); + } temp.Start(_requestConfigure); } } - void MergeParts() + private void MergeParts() { var mergeOrderedList = PartialDownloaderList.OrderBy(x => x.From); var dir = new FileInfo(FilePath).DirectoryName; Directory.CreateDirectory(dir); + using (var fs = File.OpenWrite(FilePath)) { long totalBytesWrite = 0; @@ -298,12 +317,12 @@ namespace DownKyi.Core.Downloader } } - PartialDownloader CreateNew(int order, int parts, long contentLength) + private PartialDownloader CreateNew(int order, int parts, long contentLength) { - int division = (int)contentLength / parts; - int remaining = (int)contentLength % parts; - int start = division * order; - int end = start + division - 1; + var division = contentLength / parts; + var remaining = contentLength % parts; + var start = division * order; + var end = start + division - 1; end += order == parts - 1 ? remaining : 0; return new PartialDownloader(_url, TempFileDirectory, Guid.NewGuid().ToString("N"), start, end, true); } @@ -315,15 +334,15 @@ namespace DownKyi.Core.Downloader /// public static void WaitOrResumeAll(List list, bool wait) { - foreach (var item in list) + for (var index = 0; index < list.Count; index++) { if (wait) { - item.Wait(); + list[index].Wait(); } else { - item.ResumeAfterWait(); + list[index].ResumeAfterWait(); } } } @@ -349,23 +368,21 @@ namespace DownKyi.Core.Downloader _request.ServicePoint.ConnectionLimit = 4; _requestConfigure(_request); - long ctl; using (var resp = _request.GetResponse() as HttpWebResponse) { redirectedUrl = resp.ResponseUri.OriginalString; - ctl = resp.ContentLength; + var ctl = resp.ContentLength; rangeAllowed = resp.Headers.AllKeys.Select((v, i) => new { HeaderName = v, HeaderValue = resp.Headers[i] }).Any(k => k.HeaderName.ToLower().Contains("range") && k.HeaderValue.ToLower().Contains("byte")); _request.Abort(); + return ctl; } - - return ctl; } - #endregion + #endregion 方法 #region 公共方法 @@ -374,9 +391,12 @@ namespace DownKyi.Core.Downloader /// public void Pause() { - foreach (var t in PartialDownloaderList.Where(t => !t.Completed)) + lock (this) { - t.Stop(); + foreach (var t in PartialDownloaderList.Where(t => !t.Completed)) + { + t.Stop(); + } } Thread.Sleep(200); @@ -385,34 +405,10 @@ namespace DownKyi.Core.Downloader /// /// 开始下载 /// - public void StartAsync() - { - //Task th = new Task(CreateFirstPartitions); - //th.Start(); - StartAsync(false); - } - - /// - /// 开始下载 - /// - /// - public void StartAsync(bool isWait) + public void Start() { Task th = new Task(CreateFirstPartitions); th.Start(); - - if (isWait) - { - th.Wait(); - } - } - - /// - /// 开始下载 - /// - public void Start() - { - CreateFirstPartitions(); } /// @@ -425,8 +421,8 @@ namespace DownKyi.Core.Downloader { if (PartialDownloaderList[i].Stopped) { - int from = PartialDownloaderList[i].CurrentPosition + 1; - int to = PartialDownloaderList[i].To; + var from = PartialDownloaderList[i].CurrentPosition + 1; + var to = PartialDownloaderList[i].To; if (from > to) { continue; @@ -435,13 +431,16 @@ namespace DownKyi.Core.Downloader var temp = new PartialDownloader(_url, TempFileDirectory, Guid.NewGuid().ToString(), from, to, _rangeAllowed); temp.DownloadPartProgressChanged += temp_DownloadPartProgressChanged; temp.DownloadPartCompleted += temp_DownloadPartCompleted; - PartialDownloaderList.Add(temp); + lock (this) + { + PartialDownloaderList.Add(temp); + } PartialDownloaderList[i].To = PartialDownloaderList[i].CurrentPosition; temp.Start(_requestConfigure); } } } - #endregion + #endregion 公共方法 } } diff --git a/src/DownKyi.Core/Downloader/PartialDownloader.cs b/src/DownKyi.Core/Downloader/PartialDownloader.cs index de94973..9b489c8 100644 --- a/src/DownKyi.Core/Downloader/PartialDownloader.cs +++ b/src/DownKyi.Core/Downloader/PartialDownloader.cs @@ -29,11 +29,11 @@ namespace DownKyi.Core.Downloader public event EventHandler DownloadPartStopped; private readonly AsyncOperation _aop = AsyncOperationManager.CreateOperation(null); - readonly int[] _lastSpeeds; - int _counter; + private readonly int[] _lastSpeeds; + private long _counter; + private long _to; + private long _totalBytesRead; private bool _wait; - private int _to; - private int _totalBytesRead; /// /// 下载已停止 @@ -83,7 +83,7 @@ namespace DownKyi.Core.Downloader /// /// to /// - public int To + public long To { get => _to; set @@ -96,17 +96,17 @@ namespace DownKyi.Core.Downloader /// /// from /// - public int From { get; } + public long From { get; } /// /// 当前位置 /// - public int CurrentPosition => From + _totalBytesRead - 1; + public long CurrentPosition => From + _totalBytesRead - 1; /// /// 剩余字节数 /// - public int RemainingBytes => (int)(ContentLength - _totalBytesRead); + public long RemainingBytes => ContentLength - _totalBytesRead; /// /// 完整路径 @@ -139,7 +139,7 @@ namespace DownKyi.Core.Downloader /// /// /// - public PartialDownloader(string url, string dir, string fileGuid, int from, int to, bool rangeAllowed) + public PartialDownloader(string url, string dir, string fileGuid, long from, long to, bool rangeAllowed) { From = from; _to = to; @@ -150,7 +150,7 @@ namespace DownKyi.Core.Downloader _lastSpeeds = new int[10]; } - void DownloadProcedure(Action config) + private void DownloadProcedure(Action config) { using (var file = new FileStream(FullPath, FileMode.Create, FileAccess.ReadWrite, FileShare.Delete)) { @@ -163,6 +163,7 @@ namespace DownKyi.Core.Downloader req.ServicePoint.ConnectionLimit += 1; req.ServicePoint.Expect100Continue = true; req.ProtocolVersion = HttpVersion.Version11; + req.Proxy = WebRequest.GetSystemWebProxy(); config(req); if (RangeAllowed) { @@ -265,4 +266,4 @@ namespace DownKyi.Core.Downloader _wait = false; } } -} +} \ No newline at end of file diff --git a/src/DownKyi.Core/Logging/LogManager.cs b/src/DownKyi.Core/Logging/LogManager.cs index f91abc5..3c515a3 100644 --- a/src/DownKyi.Core/Logging/LogManager.cs +++ b/src/DownKyi.Core/Logging/LogManager.cs @@ -15,7 +15,7 @@ namespace DownKyi.Core.Logging /// public class LogManager { - static readonly ConcurrentQueue> LogQueue = new ConcurrentQueue>(); + private static readonly ConcurrentQueue> LogQueue = new ConcurrentQueue>(); /// /// 自定义事件 @@ -63,14 +63,21 @@ namespace DownKyi.Core.Logging private static AutoResetEvent Pause => new AutoResetEvent(false); + private static string logDirectory; /// /// 日志存放目录,默认日志放在当前应用程序运行目录下的logs文件夹中 /// public static string LogDirectory { - get => Storage.Constant.Logs; // Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "logs"); + get => logDirectory ?? (Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory).Any(s => s.Contains("Web.config")) ? AppDomain.CurrentDomain.BaseDirectory + @"App_Data\Logs\" : Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "logs")); set { + //自定义目录 + if (!Directory.Exists(value)) + { + Directory.CreateDirectory(value); + } + logDirectory = value; } } diff --git a/src/DownKyi/Services/Download/BuiltinDownloadService.cs b/src/DownKyi/Services/Download/BuiltinDownloadService.cs index 4a4ca79..d479dc3 100644 --- a/src/DownKyi/Services/Download/BuiltinDownloadService.cs +++ b/src/DownKyi/Services/Download/BuiltinDownloadService.cs @@ -356,7 +356,7 @@ namespace DownKyi.Services.Download }; // 开始下载 - mtd.StartAsync(); + mtd.Start(); // 阻塞当前任务,监听暂停事件 while (!isComplete)