Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

C# Class To Download Files Synchronously, That Supports Cancel/Resuming And All Other Information

0.00/5 (No votes)
17 Jan 2016 2  
Downloading files from the Internet with one line without Freezing Form

Sample Image - maximum width is 600 pixels

Introduction

This class allows you to download files easily.

There many classes that allow you to download files, but with this one you'll allow to start download with simple one line and synchronously (without the need to know anything about async, await, etc.).

Problems With Getting Download Information

Most methods used background worker, but with this class I used eventhandler. What does this mean?

Write a small code to getting information.

Background

I started writing this class to support my program with a powerful download manager, because I searched a lot and couldn't find what I was looking for.

Using the Code

There are some points that I want to explain.

I need some explanation on the class code?

The class is commented well. For the most code, I explained how it works and why I use it.

How can I control more than one download file?

The answer is: a class can download one file only, so you must create a new class for each download, and but it is in a:

List< DownloadHelper.downloadFile > test = new List< DownloadHelper.downloadFile >();

So when you want to control one, just call the list like this:

test[0].cancelDownload();

Why do I need to use 'invoke' method?

You need to check if a control required invoking because in the code I used 'await Task.Run', so maybe the code will run in another thread.

What about error handling?

The class is not designed to handle error well, so you must make some modifications to the code.

Why do I use action in demo project?

Write once, call many times. Smile | :) .

How demo project works?

First, declare a list in public, so that all methods on a form can use it, like:

List<downloadhelper.downloadfile> ldf = new List<downloadhelper.downloadfile>();

Then, in download button, write the following:

try
{
    // Declare a new SaveFileDialog to select the path and file name.
    SaveFileDialog sfd = new SaveFileDialog();
    if (sfd.ShowDialog() == DialogResult.OK)
    {
        // get the count of listview == index of new item.
        int indx = list_Items.Items.Count;
        // add i new item in listview
        list_Items.Items.Add(sfd.FileName);
        for (int i = 1; i < 6; i++)
        {
            // i used this way because if try modify the subitems without
            // adding it, the program will throw error.
            list_Items.Items[indx].SubItems.Add("");
        }
           
        // Declare new class, start downloading immediate.
        DownloadHelper.downloadFile d = new DownloadHelper.downloadFile(txt_url.Text, sfd.FileName);
        ldf.Add(d); // add class to the list
        // the index of the class in the list == the index of the class in listview
        
        
        // Declare a new action because the code will run in a another thread
        // and must using invoke method.
        Action<int,int, object=""> act1 = new Action<int, 
        object="">(delegate (int idx, int sidx, object obj) 
        { list_Items.Invoke(new Action(() => 
        list_Items.Items[idx].SubItems[sidx].Text = obj.ToString())); });
        
        // handle the changes dynamically
        d.eSize += (object s1, long size) => act1.Invoke(indx, 1, size);
        d.eDownloadedSize += (object s1, long size) => act1.Invoke(indx, 2, size);
        d.eSpeed += (object s1, string size) => act1.Invoke(indx, 3, size);
        d.eDownloadState += (object s1, string size) => act1.Invoke(indx, 4, size);
    }
}
catch(Exception ex)
{
    MessageBox.Show(ex.Message);
}

Now, there many items downloading, how can I pause a specific one?

Easily in listview SelectedIndexChanged, write the following:

if (list_Items.SelectedItems.Count > 0) // if you not selecting empty item.
{
   // Get index of currently selecting item
    var indx = list_Items.SelectedItems[0].Index;
    if (list_Items.Items[indx].SubItems[4].Text == "Downloading")
    {
        btn_pause.Enabled = true;
        btn_pause.Text = "Pause";
    }
    else if (list_Items.Items[indx].SubItems[4].Text == "Paused")
    {
        btn_pause.Enabled = true;
        btn_pause.Text = "Resume";
    }
    else
    {
        btn_pause.Enabled = false;
        btn_pause.Text = "Pause/Resume";
    }
}
else
{
    btn_pause.Enabled = false;
    btn_pause.Text = "Pause/Resume";
}

In pause button, write the following:

var indx = list_Items.SelectedItems[0].Index;
if (btn_pause.Text == "Pause")
{
    ldf[indx].CancelDownload();
    btn_pause.Text = "Resume";
}
else if(btn_pause.Text == "Resume")
{
    ldf[indx].ResumeDownload();
    btn_pause.Text = "Pause";
}

History

  • 1/17/2016: First release

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here