如何从List下载文件并在进度条中显示进度

时间:2018-01-11 12:49:52

标签: c#

在我的应用程序中,我有一个包含链接的列表。

 public List<string> Urls ()
    {
        var list = new List<string>();
        list.Add("http://example.com/image.jpg");
        list.Add("http://example.com/image1.jpg");
        list.Add("http://example.com/image2.jpg");

        return list;
    }

我使用webclient进行下载。

 private void downloadAlbum_Click(object sender, EventArgs e)
{
      foreach (var link in Urls())
         {
          using (var wc = new WebClient())
                {
                    wc.DownloadFile(link.ToString(),fileName);
                }
         }
}

但是,我的胜利是滞后的。虽然WebClient可以做到这一点。 也许有人有多个下载的异步功能的例子并显示进度条中的当前进度? 更新。 我有异步等待一个文件

 private void Downloader(string link, string filepath)
    {
        using (WebClient wc = new WebClient())
        {
            wc.DownloadProgressChanged += Wc_DownloadProgressChanged;
            wc.DownloadFileCompleted += Wc_DownloadFileCompleted;
            wc.DownloadFileAsync(new Uri(link), filepath);
        }
    }

private void Wc_DownloadProgressChanged(object sender, 
DownloadProgressChangedEventArgs e)
    {
        progressBar.Value = e.ProgressPercentage;
    }

 private void Wc_DownloadFileCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
    {
        progressBar.Value = 0;

        if (e.Cancelled)
        {
            MessageBox.Show("Canceled", "Message", MessageBoxButtons.OK,MessageBoxIcon.Error);
            return;
        }

        if (e.Error != null) 
        {
            MessageBox.Show("Somethings wrong, check your internet","Message", MessageBoxButtons.OK,MessageBoxIcon.Error);

            return;
        }

        MessageBox.Show("Download is done!", "Message",MessageBoxButtons.OK,MessageBoxIcon.Information);

    }

2 个答案:

答案 0 :(得分:1)

进展值:

Tuple<DateTime, long, long> DownloadingProgress = new Tuple<DateTime, long, long>(DateTime.MinValue, 0, 0);
DownloadingProgress = new Tuple<DateTime, long, long>(DateTime.Now, 0, 0);

开始下载前请使用:

Wc.DownloadProgressChanged += DownloadProgressChanged; //when you start download

这里是DownloadProgressChanged

private void DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs downloadProgressChangedEventArgs)
{
     DownloadingProgress = new Tuple<DateTime, long, long>(DateTime.Now, downloadProgressChangedEventArgs.TotalBytesToReceive, downloadProgressChangedEventArgs.BytesReceived);
}

所以你可以看到百分比的进展:

Console.WriteLine("Downloading: " + ((DownloadingProgress.Item3 * 100) / DownloadingProgress.Item2) + "% - " + DownloadingProgress.Item2 + " / " + DownloadingProgress.Item3);

答案 1 :(得分:1)

我建议您使用 System.Net.Http.HttpClient 而不是WebClient,因为当您尝试异步下载文件时最佳做法是使用 System.Net.Http.HttpClient

我在链接中发现了这个想法:HttpClientDownload

要下载您必须使用的文件列表:

private async void DownloadFiles(List<Uri> urls)
    {
        try
        {
            Progress<double> progress = new Progress<double>();
            foreach (Uri uri in urls)
            {
                if (!client.isProcessCancel)
                {
                    //Gets download progress - pgrBarDowload is our Progress Bar
                    progress.ProgressChanged += (sender, value) => pgrBarDowload.Value = (int)value;
                }

                var cancellationToken = new CancellationTokenSource();

                writeOperation("Downloading File: " + uri.OriginalString);

                //Set files in download queue
                client.isProcessCancel = false;
                await client.DownloadFileAsync(uri.OriginalString, progress, cancellationToken.Token, directoryPath);
            }
        }
        catch (Exception ex)
        {
            writeOperation(ex.Message);
        }
}

此方法将异步下载提供的文件:

HttpClient httpClient = new HttpClient();
httpClient.Timeout = TimeSpan.FromMinutes(30);
public async Task DownloadFileAsync(string url, IProgress<double> progress, CancellationToken token, string fileDirectoryPath)
    {
        using (HttpResponseMessage response = httpClient.GetAsync(url, HttpCompletionOption.ResponseHeadersRead).Result)
        {
            response.EnsureSuccessStatusCode();

            //Get total content length
            var total = response.Content.Headers.ContentLength.HasValue ? response.Content.Headers.ContentLength.Value : -1L;
            var canReportProgress = total != -1 && progress != null;
            using (Stream contentStream = await response.Content.ReadAsStreamAsync(), fileStream = new FileStream(fileDirectoryPath + url.Substring(url.LastIndexOf('/') + 1), FileMode.Create, FileAccess.Write, FileShare.ReadWrite, 8192, true))
            {
                var totalRead = 0L;
                var totalReads = 0L;
                var buffer = new byte[8192];
                var isMoreToRead = true;

                do
                {
                    var read = await contentStream.ReadAsync(buffer, 0, buffer.Length);
                    if (read == 0)
                    {
                        isMoreToRead = false;
                    }
                    else
                    {
                        await fileStream.WriteAsync(buffer, 0, read);

                        totalRead += read;
                        totalReads += 1;

                        if (totalReads % 2000 == 0 || canReportProgress)
                        {
                            //Check if operation is cancelled by user
                            if (!isProcessCancel)
                            {
                                progress.Report((totalRead * 1d) / (total * 1d) * 100);
                            }
                            else
                            {
                                progress.Report(100);
                            }
                        }
                    }
                }
                while (isMoreToRead);
            }
        }
}

注意:进度条将单独显示每个文件的进度。此代码也针对大型媒体文件进行了测试。您还可以通过在下载开始前计算文件大小来一起设置所有文件的进度。

我在c#WinForm应用程序中创建了与文件下载,下载进度和文件操作相关的小型演示。请点击以下链接:enter link description here

如有任何建议或疑问,请随时发表评论。