[英]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.