Introduction
This class enables you to easily download multiple files in the background (via a separate thread), and will provide information about the amount of downloaded data, the percentage of completion, and the download speed. On top of this, you can cancel downloading, pause it, and of course, also resume.
Background
I started working on this class after someone on a programming help forum asked how to best download files in the background. I originally wrote it in VB.NET, but have now created a C# implementation. Check the VB.NET Background File Downloader article for the original code. Another difference with the original VB.NET implementation is that this code uses a WPF demo application, and not a Windows Forms based one.
Using the Code
Once you added the class to your project, you should be able to access it via the project's namespace
.
The first thing you need to do when using this class is (logically) create a new instance, and then add the files you want to download. You'll also need to set the local directory to which you want to download. This is pretty straight forward.
private FileDownloader downloader = new FileDownloader();
You'll also want to add some files to the list that need to be downloaded. This example demonstrates how to read each line of a WPF RichTextBox
and add it to the list:
private void btnStart_Click(object sender, RoutedEventArgs e)
{
System.Windows.Forms.FolderBrowserDialog openFolderDialog =
new System.Windows.Forms.FolderBrowserDialog();
if (openFolderDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
downloader.LocalDirectory = openFolderDialog.SelectedPath;
downloader.Files.Clear();
string rtbContents = new TextRange(rtbPaths.Document.ContentStart,
rtbPaths.Document.ContentEnd).Text;
foreach (string line in rtbContents.Split('\n'))
{
String trimmedLine = line.Trim(' ', '\r');
if (trimmedLine.Length > 0)
{
downloader.Files.Add(new FileDownloader.FileInfo(trimmedLine));
}
}
downloader.Start();
}
}
Note: The example code in this article is for a C# WPF application, and will be slightly different for a C# forms application.
The code needed to then pause, resume or cancel the downloads couldn't be simpler:
private void btnPause_Click(object sender, RoutedEventArgs e)
{
downloader.Pause();
}
private void btnResume_Click(object sender, RoutedEventArgs e)
{
downloader.Resume();
}
private void btnStop_Click(object sender, RoutedEventArgs e)
{
downloader.Stop();
}
The downloader also provides a few properties to indicate its current state: IsBusy
, IsPaused
, CanStart
, CanStop
, CanPause
and CanResume
(all booleans). Here you have an example of how to use these to set your interface:
private void downloader_StateChanged(object sender, EventArgs e)
{
btnStart.IsEnabled = downloader.CanStart;
btnStop.IsEnabled = downloader.CanStop;
btnPause.IsEnabled = downloader.CanPause;
btnResume.IsEnabled = downloader.CanResume;
rtbPaths.IsReadOnly = downloader.IsBusy;
cbUseProgress.IsEnabled = !downloader.IsBusy;
}
This is the demo code to display the progress information:
private void downloader_ProgressChanged(object sender, EventArgs e)
{
pBarFileProgress.Value = downloader.CurrentFilePercentage();
lblFileProgress.Content = String.Format("Downloaded {0} of {1} ({2}%)",
FileDownloader.FormatSizeBinary(downloader.CurrentFileProgress),
FileDownloader.FormatSizeBinary(downloader.CurrentFileSize),
downloader.CurrentFilePercentage()) + String.Format(" - {0}/s",
FileDownloader.FormatSizeBinary(downloader.DownloadSpeed));
if (downloader.SupportsProgress)
{
pBarTotalProgress.Value = downloader.TotalPercentage();
lblTotalProgress.Content = String.Format("Downloaded {0} of {1} ({2}%)",
FileDownloader.FormatSizeBinary(downloader.TotalProgress),
FileDownloader.FormatSizeBinary(downloader.TotalSize),
downloader.TotalPercentage());
}
}
Another noteworthy snippet of code is how to set the SupportsProgress
property.
private void cbUseProgress_Checked(object sender, RoutedEventArgs e)
{
downloader.SupportsProgress = (Boolean)cbUseProgress.IsChecked;
}
When the SupportProgress
property is set to true
, the file sizes will be calculated before any download is started. This can take a while, definitely when you have a large amount of files. The FileDownloader
class fires an event every time it starts checking the size of a file, which can be used to display the progress.
private void downloader_CalculationFileSize(object sender, Int32 fileNr)
{
lblStatus.Content = String.Format("Calculating file sizes -
file {0} of {1}", fileNr, downloader.Files.Count);
}
Points of Interest
The main reasons for translating my VB.NET class to C# were to both fully familiarize myself with C#, and its differences compared to VB.NET, and to exercise some WPF basics.
I'm hoping to implement some more features soon, including cancellation without deleting the files and the option to resume downloading afterwards, and the ability to download multiple files simultaneously, on separate threads.
History
- May 2nd 2009: Published the C# class and this article
- April 22nd 2009: Published an article about the VB.NET class
- April 21st 2009: Published the VB.NET class
- For the code the original VB.NET class is based upon (can be seen as an older version), see this article.
References
- Dutch support for this class can be found here.