diff --git a/BBDown/BBDownUtil.cs b/BBDown/BBDownUtil.cs index 4c041164c..2b002e37f 100644 --- a/BBDown/BBDownUtil.cs +++ b/BBDown/BBDownUtil.cs @@ -358,7 +358,7 @@ public static async Task DownloadFile(string url, string path, bool aria2c, stri try { using var progress = new ProgressBar(); - await RangeDownloadToTmpAsync(0, url, tmpName, 0, null, (_, downloaded, total) => progress.Report((double)downloaded / total)); + await RangeDownloadToTmpAsync(0, url, tmpName, 0, null, (_, downloaded, total) => progress.Report((double)downloaded / total, downloaded)); File.Move(tmpName, path, true); } catch (Exception) @@ -406,7 +406,7 @@ await Parallel.ForEachAsync(allClips, async (clip, _) => await RangeDownloadToTmpAsync(clip.index, url, tmp, clip.from, clip.to == -1 ? null : clip.to, (index, downloaded, _) => { clipProgress[index] = downloaded; - progress.Report((double)clipProgress.Values.Sum() / fileSize); + progress.Report((double)clipProgress.Values.Sum() / fileSize, clipProgress.Values.Sum()); }, true); } catch (NotSupportedException) diff --git a/BBDown/ProgressBar.cs b/BBDown/ProgressBar.cs index 7079cffad..e32235e1b 100644 --- a/BBDown/ProgressBar.cs +++ b/BBDown/ProgressBar.cs @@ -20,14 +20,21 @@ class ProgressBar : IDisposable, IProgress private bool disposed = false; private int animationIndex = 0; - public ProgressBar() + //速度计算 + private long lastDownloadedBytes = 0; + private long downloadedBytes = 0; + private string speedString = ""; + private readonly Timer speedTimer; + + public ProgressBar() { timer = new Timer(TimerHandler); + speedTimer = new Timer(SpeedTimerHandler, null, 100, 1000); - // A progress bar is only for temporary display in a console window. - // If the console output is redirected to a file, draw nothing. - // Otherwise, we'll end up with a lot of garbage in the target file. - if (!Console.IsOutputRedirected) + // A progress bar is only for temporary display in a console window. + // If the console output is redirected to a file, draw nothing. + // Otherwise, we'll end up with a lot of garbage in the target file. + if (!Console.IsOutputRedirected) { ResetTimer(); } @@ -38,20 +45,43 @@ public void Report(double value) // Make sure value is in [0..1] range value = Math.Max(0, Math.Min(1, value)); Interlocked.Exchange(ref currentProgress, value); + } + + public void Report(double value, long bytesCount) + { + // Make sure value is in [0..1] range + value = Math.Max(0, Math.Min(1, value)); + Interlocked.Exchange(ref currentProgress, value); + Interlocked.Exchange(ref downloadedBytes, bytesCount); + } + + private void SpeedTimerHandler(object? state) + { + lock (speedTimer) + { + if (disposed) return; + + if (downloadedBytes > 0) + { + speedString = " - " + BBDownUtil.FormatFileSize(downloadedBytes - lastDownloadedBytes) + "/s"; + lastDownloadedBytes = downloadedBytes; + } + } } - private void TimerHandler(object? state) + private void TimerHandler(object? state) { lock (timer) { if (disposed) return; - int progressBlockCount = (int)(currentProgress * blockCount); + int progressBlockCount = (int)(currentProgress * blockCount); int percent = (int)(currentProgress * 100); - string text = string.Format(" [{0}{1}] {2,3}% {3}", + string text = string.Format(" [{0}{1}] {2,3}% {3}{4}", new string('#', progressBlockCount), new string('-', blockCount - progressBlockCount), percent, - animation[animationIndex++ % animation.Length]); + animation[animationIndex++ % animation.Length], + speedString); UpdateText(text); ResetTimer();