[英]The operation has timed out with WebClient.DownloadFile and correct url's
我是批量上传产品到数据库。
我将图像网址下载到用于产品的网站。
我编写的代码在前25次迭代中工作正常(由于某种原因总是那个数字),但随后抛出一个System.Net.WebException“操作已经超时”。
if (!File.Exists(localFilename))
{
using (WebClient Client = new WebClient())
{
Client.DownloadFile(remoteFilename, localFilename);
}
}
我检查了它正在请求的远程URL,它是一个返回图像的有效图像URL。
此外,当我使用调试器单步执行它时,我没有收到超时错误。
救命! ;)
如果我在你的鞋子里,我会调查一些可能性:
我的钱是在后一个,因为它总是在一个很好的轮数请求中断,并且踩到调试器(又名更慢!)不会触发问题。
为了测试所有这些,我从简单的事情开始:在每次HTTP调用之前坚持延迟(Thread.Sleep),并查看问题是否消失。 如果是,请减少延迟,直到问题再次出现。 如果没有,请将延迟增加到大量(例如10秒),直到问题消失。 如果它没有消失10秒延迟,这真的是一个谜,我需要更多的信息来诊断。
如果它确实延迟了,那么你需要找出原因 - 以及限制是否是永久性的(例如服务器的防火墙,你无法改变)或者你可以改变的东西。 要获得更多信息,您需要为请求计时(例如,在每次调用之前和之后检查DateTime.Now)以查看是否看到模式。 如果时间一致并且突然变得庞大,那表明网络/防火墙/代理限制。 如果时间逐渐增加,那表明服务器正在逐渐超载并延长其请求队列。
除了对请求进行计时之外,我还要将webclient调用的超时设置为更长,这样您就可以确定超时是无限的还是仅比默认值更长。 为此,您需要WebClient类的替代方法,因为它不支持超时。 MSDN论坛上的这个主题有一个合理的替代代码示例。
在代码中添加时序的另一种方法是使用Fiddler:
似乎WebClient
没有关闭它在完成时使用的Response
对象,这会导致在你的情况下同时打开许多响应并且远程服务器上有25个连接的限制,你得到了'Timeout exception' 。 当你调试时,早期打开的响应由于它们的内部超时等而被关闭......(我认为使用Reflector的WebClient
,我找不到关闭响应的指令)。
我建议你使用HttpWebRequest & HttpWebResponse
这样你就可以在每次下载后清理对象:
HttpWebRequest request;
HttpWebResponse response = null;
try
{
FileStream fs;
Stream s;
byte[] read;
int count;
read = new byte[256];
request = (HttpWebRequest)WebRequest.Create(remoteFilename);
request.Timeout = 30000;
request.AllowWriteStreamBuffering = false;
response = (HttpWebResponse)request.GetResponse();
s = response.GetResponseStream();
fs = new FileStream(localFilename, FileMode.Create);
while((count = s.Read(read, 0, read.Length))> 0)
{
fs.Write(read, 0, count);
count = s.Read(read, 0, read.Length);
}
fs.Close();
s.Close();
}
catch (System.Net.WebException)
{
//....
}finally
{
//Close Response
if (response != null)
response.Close();
}
这是manji答案的略微简化版本:
private static void DownloadFile(Uri remoteUri, string localPath)
{
var request = (HttpWebRequest)WebRequest.Create(remoteUri);
request.Timeout = 30000;
request.AllowWriteStreamBuffering = false;
using (var response = (HttpWebResponse)request.GetResponse())
using (var s = response.GetResponseStream())
using (var fs = new FileStream(localPath, FileMode.Create))
{
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = s.Read(buffer, 0, buffer.Length)) > 0)
{
fs.Write(buffer, 0, bytesRead);
bytesRead = s.Read(buffer, 0, buffer.Length);
}
}
}
我有同样的问题,我解决了将这些行添加到配置文件app.config:
<system.net>
<connectionManagement>
<add address="*" maxconnection="100" />
</connectionManagement>
</system.net>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.