我试图下载一个客户端的数据到我的本地机器(编程),他们的web服务器非常非常慢,这导致我的WebClient对象超时。

这是我的代码:

WebClient webClient = new WebClient();

webClient.Encoding = Encoding.UTF8;
webClient.DownloadFile(downloadUrl, downloadFile);

有没有办法在这个对象上设置无限超时?如果不是,有没有人能帮我举个例子告诉我另一种方法?

该URL在浏览器中工作正常-只需要大约3分钟就能显示出来。


当前回答

你可以扩展超时:继承原始的WebClient类并重写webrequest getter来设置你自己的超时,如下例所示。

在我的例子中,MyWebClient是一个私有类:

private class MyWebClient : WebClient
{
    protected override WebRequest GetWebRequest(Uri uri)
    {
        WebRequest w = base.GetWebRequest(uri);
        w.Timeout = 20 * 60 * 1000;
        return w;
    }
}

其他回答

第一个解决方案不适合我,但这里有一些代码确实适合我。

    private class WebClient : System.Net.WebClient
    {
        public int Timeout { get; set; }

        protected override WebRequest GetWebRequest(Uri uri)
        {
            WebRequest lWebRequest = base.GetWebRequest(uri);
            lWebRequest.Timeout = Timeout;
            ((HttpWebRequest)lWebRequest).ReadWriteTimeout = Timeout;
            return lWebRequest;
        }
    }

    private string GetRequest(string aURL)
    {
        using (var lWebClient = new WebClient())
        {
            lWebClient.Timeout = 600 * 60 * 1000;
            return lWebClient.DownloadString(aURL);
        }
    }

在某些情况下,有必要在头文件中添加用户代理:

WebClient myWebClient = new WebClient();
myWebClient.DownloadFile(myStringWebResource, fileName);
myWebClient.Headers["User-Agent"] = "Mozilla/4.0 (Compatible; Windows NT 5.1; MSIE 6.0) (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)";

这就是我案子的解决办法。

信贷:

http://genjurosdojo.blogspot.com/2012/10/the-remote-server-returned-error-504.html

我昨天不得不与这个问题作斗争,我也最终写了我的自定义扩展类。

通过查看下面的代码并将其与接受的答案进行比较,您可以看到,我试图稍微调整建议,以便拥有一个更通用的类:通过这种方式,您可以在实例化对象时或在使用使用内部WebRequest处理程序的方法之前设置精确的超时。

using System;
using System.Net;

namespace Ryadel.Components.Web
{
    /// <summary>
    /// An extension of the standard System.Net.WebClient
    /// featuring a customizable constructor and [Timeout] property.
    /// </summary>
    public class RyadelWebClient : WebClient
    {
        /// <summary>
        /// Default constructor (30000 ms timeout)
        /// NOTE: timeout can be changed later on using the [Timeout] property.
        /// </summary>
        public RyadelWebClient() : this(30000) { }

        /// <summary>
        /// Constructor with customizable timeout
        /// </summary>
        /// <param name="timeout">
        /// Web request timeout (in milliseconds)
        /// </param>
        public RyadelWebClient(int timeout)
        {
            Timeout = timeout;
        }

        #region Methods
        protected override WebRequest GetWebRequest(Uri uri)
        {
            WebRequest w = base.GetWebRequest(uri);
            w.Timeout = Timeout;
            ((HttpWebRequest)w).ReadWriteTimeout = Timeout;
            return w;
        }
        #endregion

        /// <summary>
        /// Web request timeout (in milliseconds)
        /// </summary>
        public int Timeout { get; set; }
    }
}

当我在那里时,我也抓住机会将默认的Timeout值降低到30秒,因为100秒对我来说似乎太多了。

如果你需要关于这个类或如何使用它的额外信息,请查看我在博客上写的这篇文章。

正如Sohnee所说,使用System.Net.HttpWebRequest并设置Timeout属性,而不是使用System.Net.WebClient。

然而,你不能设置一个无限的超时值(它不受支持,试图这样做会抛出一个argumentoutofranceexception)。

我建议首先执行HEAD HTTP请求,检查返回的Content-Length头值,以确定您正在下载的文件中的字节数,然后为后续的GET请求相应地设置超时值,或者简单地指定一个非常长的超时值,您不会期望超过这个超时值。

你需要使用HttpWebRequest而不是WebClient,因为你不能在WebClient上设置超时而不扩展它(即使它使用HttpWebRequest)。使用HttpWebRequest将允许你设置超时。