Click here to Skip to main content
15,881,248 members
Articles / Desktop Programming / Win32
Tip/Trick

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

Rate me:
Please Sign up or sign in to vote.
4.40/5 (7 votes)
17 Jan 2016CPOL2 min read 13.7K   1.2K   20  
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:

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

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

C#
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. :).

How demo project works?

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

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

Then, in download button, write the following:

C#
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:

C#
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:

C#
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, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
Iraq Iraq
Hello, I'm Ahmed From Iraq.
I'm Developer Since When i Was 16 Years Old.
And I'm Studying Computer Science In Al-Mansour University College.
I Programming In C# And Visual Basic.NET
I Have A Basic Knowledge In C++.

Comments and Discussions

 
-- There are no messages in this forum --