using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using unfreez_wrapper;
namespace Download
{
public partial class Form1 : Form
{
List<string> urls = new List<string>();
DownloadProgressTracker tracker;
public Form1()
{
InitializeComponent();
tracker = new DownloadProgressTracker(50, TimeSpan.FromMilliseconds(500));
lblDownloadProgress.Text = "";
lblStatus.Text = "Download Pending";
lblAmount.Text = "";
lblSpeed.Text = "";
urls.Add("https://speed.hetzner.de/100MB.bin");
urls.Add("https://speed.hetzner.de/100MB.bin");
}
private async Task DownloadAsync()
{
using (var client = new WebClient())
{
client.DownloadFileCompleted += (s, e) => lblStatus.Text = "Download File Completed.";
client.DownloadProgressChanged += (s, e) => tracker.SetProgress(e.BytesReceived, e.TotalBytesToReceive);
client.DownloadProgressChanged += (s, e) => lblAmount.Text = e.BytesReceived + "/" + e.TotalBytesToReceive;
client.DownloadProgressChanged += (s, e) => lblSpeed.Text = tracker.GetBytesPerSecondString();
client.DownloadProgressChanged += (s, e) => lblDownloadSize.Text = Convert.ToInt64(client.ResponseHeaders["Content-Length"]).ToString();
client.DownloadProgressChanged += (s, e) => progressBar1.Value = e.ProgressPercentage;
client.DownloadProgressChanged += (s, e) =>
{
lblDownloadProgress.Text = "%" + e.ProgressPercentage.ToString();
lblDownloadProgress.Left = Math.Min(
(int)(progressBar1.Left + e.ProgressPercentage / 100f * progressBar1.Width),
progressBar1.Width - lblDownloadProgress.Width
);
};
for (int i = 0; i < urls.Count; i++)
{
await client.DownloadFileTaskAsync(new Uri(urls[i]), @"d:\satImages\img" + i + ".gif");
}
}
}
private void Form1_Load(object sender, EventArgs e)
{
}
private async void btnStart_Click(object sender, EventArgs e)
{
lblStatus.Text = "Downloading...";
await DownloadAsync();
}
private void btnStop_Click(object sender, EventArgs e)
{
lblStatus.Text = "Download Stopped";
}
}
}
And the class DownloadProgressTracker :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Download
{
class DownloadProgressTracker
{
private long _totalFileSize;
private readonly int _sampleSize;
private readonly TimeSpan _valueDelay;
private DateTime _lastUpdateCalculated;
private long _previousProgress;
private double _cachedSpeed;
private Queue<Tuple<DateTime, long>> _changes = new Queue<Tuple<DateTime, long>>();
public DownloadProgressTracker(int sampleSize, TimeSpan valueDelay)
{
_lastUpdateCalculated = DateTime.Now;
_sampleSize = sampleSize;
_valueDelay = valueDelay;
}
public void NewFile()
{
_previousProgress = 0;
}
public void SetProgress(long bytesReceived, long totalBytesToReceive)
{
_totalFileSize = totalBytesToReceive;
long diff = bytesReceived - _previousProgress;
if (diff <= 0)
return;
_previousProgress = bytesReceived;
_changes.Enqueue(new Tuple<DateTime, long>(DateTime.Now, diff));
while (_changes.Count > _sampleSize)
_changes.Dequeue();
}
public double GetProgress()
{
return _previousProgress / (double)_totalFileSize;
}
public string GetProgressString()
{
return String.Format("{0:P0}", GetProgress());
}
public string GetBytesPerSecondString()
{
double speed = GetBytesPerSecond();
var prefix = new[] { "", "K", "M", "G" };
int index = 0;
while (speed > 1024 && index < prefix.Length - 1)
{
speed /= 1024;
index++;
}
int intLen = ((int)speed).ToString().Length;
int decimals = 3 - intLen;
if (decimals < 0)
decimals = 0;
string format = String.Format("{<!-- -->{0:F{0}}}", decimals) + "{1}B/s";
return String.Format(format, speed, prefix[index]);
}
public double GetBytesPerSecond()
{
if (DateTime.Now >= _lastUpdateCalculated + _valueDelay)
{
_lastUpdateCalculated = DateTime.Now;
_cachedSpeed = GetRateInternal();
}
return _cachedSpeed;
}
private double GetRateInternal()
{
if (_changes.Count == 0)
return 0;
TimeSpan timespan = _changes.Last().Item1 - _changes.First().Item1;
long bytes = _changes.Sum(t => t.Item2);
double rate = bytes / timespan.TotalSeconds;
if (double.IsInfinity(rate) || double.IsNaN(rate))
return 0;
return rate;
}
}
}
In the screenshot two problem :
- The Download Amount should show the current downloaded size out of the completed file size but it show it as a very long number and I need it to be show in some other size unit. Something the user can read it easier.