如果失败,如何使webclient重新下载文件?

时间:2018-11-10 11:42:43

标签: c# webclient

我正在尝试使用foreach将图像的链接列表下载到服务器(最多40个链接)。

就我而言,有时该链接存在,但我不知道为什么它会捕获并取消下一个链接的下载。也许需要稍等一下?因为当我调试应用程序时,我看到链接被应用程序跳过并去捕获了,但是有时它在浏览器中几秒钟后就打开了,因此我尝试下载的服务器的响应时间有时需要更多时间来加载和打开链接。

   string newPath = "~/data/" + model.PostID + "/" + name + "/";

   //test1 is a list of links
                foreach (var item1 in test1)
                {

                    HttpWebRequest request = WebRequest.Create(item1) as HttpWebRequest; request.Method = "HEAD";
                    try
                    {
                        using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
                        {
                            var webClient = new WebClient();
                            string path = newPath + i + ".jpg";
                            webClient.DownloadFileAsync(new Uri(item1), Server.MapPath(path));
                            string newlinks = "https://example.com/data/" + chapter.PostID + "/" + name + "/" + i + ".jpg";
                            allimages = allimages + newlinks + ',';
                            response.Close();
                            i++;

                        }
                    }

                    catch
                    {                           
                        break;
                    }



                }

现在,我的主要目标是解决此问题,但正如我在调试中所看到的:

  1. 我要下载的图像链接存在

  2. 有时需要更多时间来回复

那么我该如何解决呢?当下载取消并存在链接时,该怎么办?

3 个答案:

答案 0 :(得分:0)

您可以使用以下示例:

    class WebClientUtility : WebClient
    {
        public int Timeout { get; set; }

        public WebClientUtility() : this(60000) { }

        public WebClientUtility(int timeout)
        {
            this.Timeout = timeout;
        }

        protected override WebRequest GetWebRequest(Uri address)
        {
            var request = base.GetWebRequest(address);
            if (request != null)
            {
                request.Timeout = Timeout;
            }
            return request;
        }
    }

    //
    public class DownloadHelper : IDisposable
    {
        private WebClientUtility _webClient;
        private string _downloadUrl;
        private string _savePath;
        private int _retryCount;

        public DownloadHelper(string downloadUrl, string savePath)
        {
            _savePath = savePath;
            _downloadUrl = downloadUrl;

            _webClient = new WebClientUtility();

            _webClient.DownloadFileCompleted += ClientOnDownloadFileCompleted;
        }


        public void StartDownload()
        {
            _webClient.DownloadFileAsync(new Uri(_downloadUrl), _savePath);
        }

        private void ClientOnDownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
        {
            if (e.Error != null)
            {
                _retryCount++;

                if (_retryCount < 3)
                {
                    _webClient.DownloadFileAsync(new Uri(_downloadUrl), _savePath);
                }
                else
                {
                    Console.WriteLine(e.Error.Message);
                }
            }
            else
            {
                _retryCount = 0;
                Console.WriteLine($"successfully download: # {_downloadUrl}  to  # {_savePath}");
            }
        }
        public void Dispose()
        {
            _webClient.Dispose();
        }
    }

    //
    class Program
    {

        private static void Main(string[] args)
        {
            for (int i = 0; i < 100; i++)
            {
                var downloadUrl = $@"https://example.com/mag-{i}.pdf";
                var savePath = $@"D:\DownloadFile\FileName{i}.pdf";

                DownloadHelper downloadHelper = new DownloadHelper(downloadUrl, savePath);

                downloadHelper.StartDownload();
            }

            Console.ReadLine();
        }
    }

要解决超时问题,可以创建派生类并设置基本WebRequest类的timeout属性,并 要重试,您可以使用WebClient的DownloadFileCompleted事件并在那里实现重试模式

答案 1 :(得分:0)

您正在使用'DownloadFileAsync'的异步版本。但是,您不是awaiting的电话,这会带来无法预测的行为。

设置方法async,然后使用此方法:

await webClient.DownloadFileAsync(new Uri(item1), Server.MapPath(path));

答案 2 :(得分:0)

这解决了我的情况:

await Task.Run(() =>
                {
                    webClient.DownloadFileAsync(new Uri(item1), Server.MapPath(path));
                });