下载文件时如何显示进度栏?

时间:2019-02-02 21:16:24

标签: c# .net winforms

我是使用c#进行编码的新手,所以有人可以告诉我如何在其中包含代码以显示文件下载的进度条吗?

    private void button4_Click(object sender, EventArgs e)
    {
        using (var client = new WebClient())
        {
            MessageBox.Show("File will start downloading");

            var path = System.IO.Path.Combine(System.IO.Path.GetTempPath(), "SOMEFILENAME.exe");

            client.DownloadFile("GOOGLE DRIVE LINK", path);

            MessageBox.Show("File has been downloaded!");

            System.Diagnostics.Process.Start(path);
        }
    }

1 个答案:

答案 0 :(得分:1)

要更新进度条的同时您的WebClient下载数据,你必须使用确实在背景这个任务的功能。 WebClient具有称为有用的功能DownloadFileAsync。该功能的作用完全是:在后台下载。

在的代码,以便与此变化:

private void button4_Click(object sender, EventArgs e)
{
    using (var client = new WebClient())
    {
        MessageBox.Show("File will start downloading");

        var path = System.IO.Path.Combine(System.IO.Path.GetTempPath(), "SOMEFILENAME.exe");

        client.DownloadFileAsync(new Uri("GOOGLE DRIVE LINK"), path);

        MessageBox.Show("File has been downloaded!");

        System.Diagnostics.Process.Start(path);
    }
}

很遗憾,我们现在遇到了问题。该方法开始在后台下载和你的代码立即继续。这意味着您按下按钮时,第一个消息框弹出,第二个消息框后的第一个正确弹出,如果没有完成你的下载,当你关闭你的文件过早执行第二个。

为避免这种情况,WebClient个事件。在一个我们需要的是一个名为DownloadFileCompleted。顾名思义,下载完成后,它将执行您想要的任何操作。因此,让我们看一下新代码:

string path = System.IO.Path.Combine(System.IO.Path.GetTempPath(), "SOMEFILENAME.exe"); // We need our path to be global

private void button4_Click(object sender, EventArgs e)
{
    using (var client = new WebClient())
    {
        client.DownloadFileCompleted += client_DownloadFileCompleted; // Add our new event handler
        MessageBox.Show("File will start downloading");

        client.DownloadFileAsync(new Uri("GOOGLE DRIVE LINK"), path);
    }
}

private void client_DownloadFileCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e) // This is our new method!
{
    MessageBox.Show("File has been downloaded!");

    System.Diagnostics.Process.Start(path);
}

我们的下一个问题:client在using块内。这是伟大的前景下载,但如果我们这样做异步(这就是做它在后台调用)您的client将尽快离开该块是下载已后立即死亡的开始即可。因此,让我们成为client的全局对象,以便以后可以销毁它。

string path = System.IO.Path.Combine(System.IO.Path.GetTempPath(), "SOMEFILENAME.exe");
WebClient client; // Here it is!

private void button4_Click(object sender, EventArgs e)
{
    client = new WebClient(); // Create a new client here
    client.DownloadFileCompleted += client_DownloadFileCompleted; // Add our new event handler
    MessageBox.Show("File will start downloading");

    client.DownloadFileAsync(new Uri("GOOGLE DRIVE LINK"), path);
}

private void client_DownloadFileCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e) // This is our new method!
{
    MessageBox.Show("File has been downloaded!");

    System.Diagnostics.Process.Start(path);
}

private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
    if (client != null)
        client.Dispose(); // We have to delete our client manually when we close the window or whenever you want
}

现在让我们假设用户可以在下载完成之前再次按下按钮。我们的客户将被覆盖,然后下载将被取消。所以我们就忽略了按下按钮,如果我们已经下载东西,只有创造新的客户,如果我们没有一个。新代码:

string path = System.IO.Path.Combine(System.IO.Path.GetTempPath(), "SOMEFILENAME.exe");
WebClient client;

private void button4_Click(object sender, EventArgs e)
{
    if (client != null && client.IsBusy) // If the client is already downloading something we don't start a new download
            return;

    if (client == null) // We only create a new client if we don't already have one
    {
        client = new WebClient(); // Create a new client here
        client.DownloadFileCompleted += client_DownloadFileCompleted; // Add our new event handler
    }
    MessageBox.Show("File will start downloading");

    client.DownloadFileAsync(new Uri("GOOGLE DRIVE LINK"), path);
}

private void client_DownloadFileCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e) // This is our new method!
{
    MessageBox.Show("File has been downloaded!");

    System.Diagnostics.Process.Start(path);
}

private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
    if (client != null)
        client.Dispose(); // We have to delete our client manually when we close the window or whenever you want
}

现在完成了无聊的部分,让我们开始解决您的问题:在进度栏中查看进度。 WebClient有另一个名为DownloadProgressChanged的事件。我们可以用它来更新我们的进度条。

谈论进度栏:在Windows窗体中,可以通过在Visual Studio的工具弓窗口中搜索ProgressBar来创建一个。然后将其放在窗口中的某个位置。 ProgressBar组件具有一些对其范围很重要的属性。很幸运,默认值正是我们所需要的。

我们更新的代码(假设您的进度条称为progressBar1

string path = System.IO.Path.Combine(System.IO.Path.GetTempPath(), "SOMEFILENAME.exe");
WebClient client;

private void button4_Click(object sender, EventArgs e)
{
    if (client != null && client.IsBusy) // If the client is already downloading something we don't start a new download
            return;

    if (client == null) // We only create a new client if we don't already have one
    {
        client = new WebClient(); // Create a new client here
        client.DownloadFileCompleted += client_DownloadFileCompleted;
        client.DownloadProgressChanged += client_DownloadProgressChanged; // Add new event handler for updating the progress bar
    }
    MessageBox.Show("File will start downloading");

    client.DownloadFileAsync(new Uri("GOOGLE DRIVE LINK"), path);
}

private void client_DownloadFileCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e) // This is our new method!
{
    MessageBox.Show("File has been downloaded!");

    System.Diagnostics.Process.Start(path);
}

private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
    if (client != null)
        client.Dispose(); // We have to delete our client manually when we close the window or whenever you want
}

private void client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e) // NEW
{
    progressBar1.Value = e.ProgressPercentage;
}

注意:

  1. 您可以通过双击窗口的属性框中的FormClosing事件来创建FormClosing方法。
  2. 仅当关闭窗口后程序没有退出时才需要调用client.Dispose()。在任何其他情况下,您都可以完全摆脱FormClosing的东西。

到此为止。我希望这不是太长,你和我可以帮你。随时要求澄清。这就是评论是那里。