This is the class for the downloading
using System;
using System.IO;
using System.Net.Http;
using System.Threading.Tasks;
namespace Downloading_Test
{
public class DownloadingCore
{
public class DownloadeCompletedEventArgs : EventArgs
{
public bool IsSuccess { get; set; }
public string FilePath { get; set; } = string.Empty; // Initialize with an empty string
}
public class DownloadProgressEventArgs : EventArgs
{
public int Percentage { get; set; }
}
public class DownloadManager
{
public long ContentLength { get; private set; } // Expose ContentLength as a property
public event EventHandler<DownloadeCompletedEventArgs>? DownloadCompleted;
public event EventHandler<DownloadProgressEventArgs>? DownloadProgress;
public async Task StartDownload(string url, string filePath)
{
try
{
using (var client = new HttpClient())
{
var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead);
response.EnsureSuccessStatusCode();
ContentLength = response.Content.Headers.ContentLength.GetValueOrDefault(); // Set ContentLength
var totalBytesRead = 0L;
using (var contentStream = await response.Content.ReadAsStreamAsync())
using (var fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None))
{
var buffer = new byte[8192];
int bytesRead;
while ((bytesRead = await contentStream.ReadAsync(buffer, 0, buffer.Length)) > 0)
{
await fileStream.WriteAsync(buffer, 0, bytesRead);
totalBytesRead += bytesRead;
if (ContentLength > 0)
{
var progressPercentage = (int)((float)totalBytesRead / ContentLength * 100);
OnDownloadProgress(new DownloadProgressEventArgs { Percentage = progressPercentage });
}
}
}
OnDownloadCompleted(new DownloadeCompletedEventArgs { IsSuccess = true, FilePath = filePath });
}
}
catch (Exception ex)
{
string exx = ex.ToString();
OnDownloadCompleted(new DownloadeCompletedEventArgs { IsSuccess = false, FilePath = filePath });
}
}
protected virtual void OnDownloadCompleted(DownloadeCompletedEventArgs e)
{
DownloadCompleted?.Invoke(this, e);
}
protected virtual void OnDownloadProgress(DownloadProgressEventArgs e)
{
DownloadProgress?.Invoke(this, e);
}
}
}
}
This is the form1 code. I added a variable s_cts and make instance for CancellationTokenSource.
In the button click event where the downloading start, I change the button text to "Stop"
and then I want that when the button text is Stop and then if clicking the button, it will stop everything in the middle and will reset everything and change the button text back to "Download"
using System;
using System.Diagnostics;
using System.IO;
using System.Windows.Forms;
using Downloading_Test;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;
namespace Downloading_Test
{
public partial class Form1 : Form
{
private string _saveDir = @"D:\Downloads\";
private DownloadingCore.DownloadManager _downloadManager = new DownloadingCore.DownloadManager();
private string _fileUrl = "https://hil-speed.hetzner.com/100MB.bin";
private Stopwatch _stopwatch = new Stopwatch();
private DateTime _startTime;
private TimeSpan _elapsedTime;
private Logger logger = new Logger();
private int downloadsCounter = 0;
private CancellationTokenSource s_cts = new CancellationTokenSource();
List<string> sites = new List<string>
{
"https://hil-speed.hetzner.com/100MB.bin",
"https://hil-speed.hetzner.com/100MB.bin",
"https://hil-speed.hetzner.com/100MB.bin"
// Add more URLs as needed
};
public Form1()
{
InitializeComponent();
InitializeDownloadManager();
}
private void InitializeDownloadManager()
{
_downloadManager.DownloadProgress += DownloadManager_DownloadProgress;
_downloadManager.DownloadCompleted += DownloadManager_DownloadCompleted;
}
private void DownloadManager_DownloadCompleted(object? sender, DownloadingCore.DownloadeCompletedEventArgs e)
{
logger.LogDownloadCompleted(e.IsSuccess, _elapsedTime);
progressBar1.Value = 0;
_stopwatch.Stop();
if (e.IsSuccess && downloadsCounter > 0)
{
downloadsCounter--;
}
if (downloadsCounter == 0)
{
logger.LogDownloadCompleted();
Download.Enabled = true;
}
logger.GetLog(richTextBoxLogger);
}
private void DownloadManager_DownloadProgress(object? sender, DownloadingCore.DownloadProgressEventArgs e)
{
progressBar1.Value = e.Percentage;
if (_stopwatch.IsRunning)
{
// Calculate elapsed time since the download started
_elapsedTime = DateTime.Now - _startTime;
if (_elapsedTime.TotalSeconds > 0)
{
// Calculate the actual number of bytes downloaded
long totalBytes = e.Percentage * _downloadManager.ContentLength / 100;
// Calculate download speed
double speed = totalBytes / _elapsedTime.TotalSeconds;
// Calculate time left to download
double remainingBytes = _downloadManager.ContentLength - totalBytes;
double remainingTime = (speed > 0) ? remainingBytes / speed : 0;
// Update labels
labelDownloadSpeed.Text = "Speed: " + FormatBytes(speed) + "/s";
labelProgress.Text = $"Downloaded: {FormatBytes(totalBytes)} / {FormatBytes(_downloadManager.ContentLength)}";
labelTimeLeft.Text = "Time Left: " + FormatTimeSpan(TimeSpan.FromSeconds(remainingTime));
labelTimeElapsed.Text = "Time Elapsed: " + FormatTimeSpan(_elapsedTime);
}
}
}
public static string FormatBytes(double bytes)
{
const int scale = 1024;
string[] units = { "B", "KB", "MB", "GB", "TB", "PB", "EB" };
if (bytes <= 0)
{
return "0 B";
}
int magnitude = (int)Math.Floor(Math.Log(bytes, scale));
int index = Math.Min(magnitude, units.Length - 1);
double adjustedSize = bytes / Math.Pow(scale, index);
string format = (index >= 0 && index < 3) ? "F2" : "F0";
return $"{adjustedSize.ToString(format)} {units[index]}";
}
private async void Download_Click(object sender, EventArgs e)
{
Download.Text = "Stop";
downloadsCounter = sites.Count;
foreach (string site in sites)
{
var fileName = Path.GetFileName(site);
var fileSavePath = Path.Combine(_saveDir, fileName);
try
{
logger.LogStartDownload(fileName, site);
logger.GetLog(richTextBoxLogger);
_stopwatch.Reset();
_stopwatch.Start();
_startTime = DateTime.Now;
if (File.Exists(fileSavePath))
{
File.Delete(fileSavePath);
}
await _downloadManager.StartDownload(site, fileSavePath);
}
catch (Exception ex)
{
logger.LogDownloadCompleted(false, _elapsedTime);
}
}
}
private string FormatTimeSpan(TimeSpan timeSpan)
{
return $"{timeSpan.Hours:D2}:{timeSpan.Minutes:D2}:{timeSpan.Seconds:D2}";
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
}
}
}