【问题标题】:How download files from List and show progress in progress bar如何从列表下载文件并在进度条中显示进度
【发布时间】:2018-01-11 12:49:51
【问题描述】:

在我的应用中,我有一个带有链接的列表。

 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;
    }

我使用网络客户端进行下载。

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

但是,我的 winform 落后了。而 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);

    }

【问题讨论】:

  • 您是否尝试过使用async 却失败了?最好表现出你的一些努力,因为你似乎已经知道该做什么了。
  • 从单独的线程下载,然后用调度器调整进度值
  • 为什么要在列表中声明一个新列表然后返回它?它不会失去作用域吗?
  • 任何可以提高我的编码技能的帮助都会对我有用:)

标签: c#


【解决方案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);

【讨论】:

    【解决方案2】:

    我建议您使用 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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-26
      相关资源
      最近更新 更多