C# 网络客户端不';如果给定URI列表,则无法下载所有文件
我正在使用C# 网络客户端不';如果给定URI列表,则无法下载所有文件,c#,.net,asynchronous,download,webclient,C#,.net,Asynchronous,Download,Webclient,我正在使用列表和网络客户端类制作一个从互联网上同时下载图像的工具。以下是相关代码: 我正在使用的新WebClient: public class PatientWebClient : WebClient { protected override WebRequest GetWebRequest(Uri uri) { WebRequest w = base.GetWebRequest(uri); w.Timeout = Timeout.Infinit
列表
和网络客户端
类制作一个从互联网上同时下载图像的工具。以下是相关代码:
我正在使用的新WebClient:
public class PatientWebClient : WebClient
{
protected override WebRequest GetWebRequest(Uri uri)
{
WebRequest w = base.GetWebRequest(uri);
w.Timeout = Timeout.Infinite;
return w;
}
}
下载方法如下:
public static void DownloadFiles()
{
string filename = string.Empty;
while (_count < _images.Count())
{
PatientWebClient client = new PatientWebClient();
client.DownloadDataCompleted += DownloadCompleted;
filename = _images[_count].Segments.Last().ToString();
if (!File.Exists(_destinationFolder + @"\" + filename))
{
try
{
client.DownloadDataAsync(_images[_count], _images[_count]);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
++_count;
}
}
private static void DownloadCompleted(object sender, DownloadDataCompletedEventArgs e)
{
if (e.Error == null)
{
Uri uri = (Uri)e.UserState;
string saveFilename = uri.Segments.Last().ToString();
byte[] fileData = e.Result;
if (saveFilename.EndsWith(".jpg") || saveFilename.EndsWith(".png") || saveFilename.EndsWith(".gif"))
using (FileStream fileStream = new FileStream(_destinationFolder + @"\" + saveFilename, FileMode.Create))
fileStream.Write(fileData, 0, fileData.Length);
else
using (FileStream fileStream = new FileStream(_destinationFolder + @"\" + saveFilename + ".jpg", FileMode.Create))
fileStream.Write(fileData, 0, fileData.Length);
++_downloadedCounter;
((WebClient)sender).Dispose();
}
}
publicstaticvoiddownloadfiles()
{
字符串文件名=string.Empty;
而(_count<_images.count())
{
PatientWebClient=新的PatientWebClient();
client.DownloadDataCompleted+=下载完成;
文件名=_图像[_计数].Segments.Last().ToString();
如果(!File.Exists(\u destinationFolder+@“\”+filename))
{
尝试
{
client.DownloadDataAsync(_images[_count],_images[_count]);
}
捕获(例外情况除外)
{
Console.WriteLine(例如ToString());
}
}
++_计数;
}
}
私有静态void下载已完成(对象发送方,DownloadDataCompletedEventArgs e)
{
如果(e.Error==null)
{
Uri=(Uri)e.UserState;
string saveFilename=uri.Segments.Last().ToString();
字节[]文件数据=e.结果;
if(saveFilename.EndsWith(“.jpg”)| | saveFilename.EndsWith(“.png”)| | saveFilename.EndsWith(“.gif”))
使用(FileStream FileStream=newfilestream(\u destinationFolder+@“\”+saveFilename,FileMode.Create))
Write(fileData,0,fileData.Length);
其他的
使用(FileStream FileStream=newfilestream(\u destinationFolder+@“\”+saveFilename+.jpg”,FileMode.Create))
Write(fileData,0,fileData.Length);
++_下载计数器;
((WebClient)发送方).Dispose();
}
}
问题在于并非列表中的所有图像都被下载。如果我第二次点击下载按钮,将会下载更多的内容,实际上需要点击几下才能将所有内容下载下来。
WebClient
s是否超时,如果超时,是否有办法让他们自动重试下载?如果没有,解决此问题的正确方法是什么?我的意思是,设置webclient的超时并捕获错误:
internal class Program
{
private static void Main(string[] args)
{
Uri[] uris = {new Uri("http://www.google.com"), new Uri("http://www.yahoo.com")};
Parallel.ForEach(uris, uri =>
{
using (var webClient = new MyWebClient())
{
try
{
var data = webClient.DownloadData(uri);
// Success, do something with your data
}
catch (Exception ex)
{
// Something is wrong...
Console.WriteLine(ex.ToString());
}
}
});
}
}
public class MyWebClient : WebClient
{
protected override WebRequest GetWebRequest(Uri uri)
{
var w = base.GetWebRequest(uri);
w.Timeout = 5000; // 5 seconds timeout
return w;
}
}
我的意思是,设置webclient的超时并捕获错误:
internal class Program
{
private static void Main(string[] args)
{
Uri[] uris = {new Uri("http://www.google.com"), new Uri("http://www.yahoo.com")};
Parallel.ForEach(uris, uri =>
{
using (var webClient = new MyWebClient())
{
try
{
var data = webClient.DownloadData(uri);
// Success, do something with your data
}
catch (Exception ex)
{
// Something is wrong...
Console.WriteLine(ex.ToString());
}
}
});
}
}
public class MyWebClient : WebClient
{
protected override WebRequest GetWebRequest(Uri uri)
{
var w = base.GetWebRequest(uri);
w.Timeout = 5000; // 5 seconds timeout
return w;
}
}
如果仍要使用该模式,此模式没有超时,则必须使用计时器实现该模式:
internal class Program
{
private static int _downloadCounter;
private static readonly object _syncObj = new object();
private static void Main(string[] args)
{
Uri[] uris = {new Uri("http://www.google.com"), new Uri("http://www.yahoo.com")};
foreach (var uri in uris)
{
var webClient = new WebClient();
webClient.DownloadDataCompleted += OnWebClientDownloadDataCompleted;
webClient.DownloadDataAsync(uri);
}
Thread.Sleep(Timeout.Infinite);
}
private static void OnWebClientDownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e)
{
if (e.Error == null)
{
// OK
Console.WriteLine(Encoding.UTF8.GetString(e.Result));
}
else
{
// Error
Console.WriteLine(e.Error.ToString());
}
lock (_syncObj)
{
_downloadCounter++;
Console.WriteLine("Counter = {0}", _downloadCounter);
}
var webClient = sender as WebClient;
if (webClient == null) return;
webClient.DownloadDataCompleted -= OnWebClientDownloadDataCompleted;
webClient.Dispose();
}
}
如果仍要使用该模式,此模式没有超时,则必须使用计时器实现该模式:
internal class Program
{
private static int _downloadCounter;
private static readonly object _syncObj = new object();
private static void Main(string[] args)
{
Uri[] uris = {new Uri("http://www.google.com"), new Uri("http://www.yahoo.com")};
foreach (var uri in uris)
{
var webClient = new WebClient();
webClient.DownloadDataCompleted += OnWebClientDownloadDataCompleted;
webClient.DownloadDataAsync(uri);
}
Thread.Sleep(Timeout.Infinite);
}
private static void OnWebClientDownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e)
{
if (e.Error == null)
{
// OK
Console.WriteLine(Encoding.UTF8.GetString(e.Result));
}
else
{
// Error
Console.WriteLine(e.Error.ToString());
}
lock (_syncObj)
{
_downloadCounter++;
Console.WriteLine("Counter = {0}", _downloadCounter);
}
var webClient = sender as WebClient;
if (webClient == null) return;
webClient.DownloadDataCompleted -= OnWebClientDownloadDataCompleted;
webClient.Dispose();
}
}
尝试使用超时扩展webclient。Webclient没有超时功能。如果e.错误!=null,那里发生了什么?@Stanley你能澄清你的问题吗?添加一些日志或
控制台。WriteLine
语句,这样你就知道实际发生了什么。写出事件参数中的计数器、文件名、url和(如@Stanley所示)以及错误。另外,请尝试在每个下载完成的调用的末尾添加fileString.Flush()
。@mdisibio您的意思是fileStream.Flush()
?synchronize\u destinationfolder和\u downloadcounter尝试用超时扩展webclient。Webclient没有超时功能。如果e.错误!=null,那里发生了什么?@Stanley你能澄清你的问题吗?添加一些日志或控制台。WriteLine
语句,这样你就知道实际发生了什么。写出事件参数中的计数器、文件名、url和(如@Stanley所示)以及错误。另外,尝试在每个下载完成的调用的末尾添加fileString.Flush()
。@mdisibio您的意思是fileStream.Flush()
?synchronize\u destinationfolder and\u downloadCounter原始帖子的问题不是超时。问题是在不等待异步下载任务完成的情况下启动该任务。Stanley的Parallel.ForEach方法是优雅而有效地解决该问题的一种方法。@EugeneShvets MSFT我正在测试他建议的代码的行为。将更新。@EugeneShvets MSFT这种方法只会导致大约30个文件被下载,而我用我的方法得到大约300个文件。我也没有收到任何错误,所以我不确定发生了什么。在启动(client.DownloadDataAsync(_images[_count],_images[_count]))之后,webclient的问题将在不等待完成的情况下得到解决。@Stanley我已经更新了原始帖子,目前正在测试它。WebClient
现在只有在下载文件后才能处理。您的想法将不胜感激。原始帖子的问题不是超时。问题是在不等待异步下载任务完成的情况下启动该任务。Stanley的Parallel.ForEach方法是优雅而有效地解决该问题的一种方法。@EugeneShvets MSFT我正在测试他建议的代码的行为。将更新。@EugeneShvets MSFT这种方法只会导致大约30个文件被下载,而我用我的方法得到大约300个文件。我也没有收到任何错误,所以我不确定发生了什么。在启动(client.DownloadDataAsync(_images[_count],_images[_count]))之后,webclient的问题将在不等待完成的情况下得到解决。@Stanley我已经更新了原始帖子,目前正在测试它。WebClient
现在只有在下载文件后才能处理。非常感谢您的想法。对于\u downloadedCounter
,我想我将使用联锁.Increment(参考但是现在我把这个标记为答案,并将做更多的测试。感谢您的帮助和建议。有时,这会有所帮助:ServicePointManager.DefaultConnectionLim