2012-07-11 141 views
0

我试图下载多个文件,但它没有按照我的希望工作。 有人能告诉我这个脚本有什么问题吗,因为我已经尝试了很多东西,真的不知道该怎么做了。下载多个文件WebClient

public static void DownloadFile(string url) 
     { 
      WebClient client = new WebClient(); 
      var name = url.Substring(url.LastIndexOf('/')).Remove(0, 1); 
      foreach (var item in urls) 
      { 
       client.DownloadFile(item, "C:\\" + name); 
      } 
     } 

     private void btnGo_Click(object sender, EventArgs e) 
     { 
      urls.Add("url1"); 
      urls.Add("url2"); 
      urls.Add("url3"); 
      Parallel.ForEach(urls, 
       new ParallelOptions { MaxDegreeOfParallelism = 10 }, 
       DownloadFile); 
     } 

using (var sr = new StreamReader(HttpWebRequest.Create(url).GetResponse().GetResponseStream())) 
      { 
       using (var sw = new StreamWriter(url.Substring(url.LastIndexOf('/')))) 
       { 
        sw.Write(sr.ReadToEnd()); 
       } 
      } 
+0

答案就在这里 http://stackoverflow.com/questions/6992553/how-do-i-async-download-multiple-files-using-webclient-but-one-at-a-time – 2012-07-11 01:36:02

+0

@GX。我已经尝试过,但无法完成它的工作:(。 – 2012-07-11 01:39:13

+0

你的代码在哪里准确地打破?你调试了吗? – 2012-07-11 01:41:53

回答

5

我会用System.Net.HttpWebRequest代替。

这是代码会是什么样子:

private List<string> urls = new List<string>(); 

private void btnGo_Click(object sender, EventArgs e) 
{ 
    urls.Add("http://199.91.152.106/ua0p3fbc5nlg/gg2w2fq4ljc1nnd/MicroCraft_Beta.zip"); 
    Parallel.ForEach(urls, new ParallelOptions { MaxDegreeOfParallelism = 10 }, DownloadFile); 
} 

public static void DownloadFile(string url) 
{ 
    var req = (HttpWebRequest)WebRequest.Create(url); 
    var name = url.Substring(url.LastIndexOf('/') + 1); 
    using (var res = (HttpWebResponse)req.GetResponse()) 
    using (var resStream = res.GetResponseStream()) 
    using (var fs = new FileStream("C:\\" + name, FileMode.Create, FileAccess.Write, FileShare.None)) 
    { 
     // Save to file 
     var buffer = new byte[8 * 1024]; // 8 KB buffer 
     int len; // Read count 
     while ((len = resStream.Read(buffer, 0, buffer.Length)) > 0) 
      fs.Write(buffer, 0, buffer.Length); 
    } 
} 

因为你对我的评论的URL不使用HTTP协议的正确执行。你必须这样才能添加到您的配置文件,它的工作(无论是App.config中或Web.config文件,这取决于它是否是一个ASP.Net网站或离线应用):

<system.net> 
    <settings> 
     <httpWebRequest useUnsafeHeaderParsing="true" /> 
    </settings> 
</system.net> 

至于你的名字碰撞问题与你在评论中说的相同,这应该通过将你的var name = url.Substring(url.LastIndexOf('/')).Remove(0, 1);改成别的东西来解决。

如果你想有一个增量的文件名,你可以这样做:

// Inside your class: 
private static int counter = 0; 

// In your method: 
var name = "file" + System.Threading.Interlocked.Increment(ref counter) + ".html"; 
+0

我找到了一个脚本来做到这一点,我将它添加到我的文章,但这也没有工作:(。 – 2012-07-11 01:36:54

+0

@Aidiakapi嗡嗡声...不... WebClient是什么这里使用shoudl http://msdn.microsoft.com/en-us/library/system.net.webclient(v=vs.80).aspx看一下DownloadFile函数 – 2012-07-11 01:38:08

+0

@GX。'WebClient' * can *用于此目的,但实质上'WebClient'不过是IE浏览器的一个奇妙的包装,另一方面'HttpWebRequest'是这个的基本要求。 – Aidiakapi 2012-07-11 01:43:21

1

您正在下载中,假定单一调用该函数下载的所有文件的DownloadFile代码到同一个文件中的所有文件。

修正:

选项1:不要使用Parallel.ForEach和简单地调用DownloadFile一次。为每个下载指定唯一的文件名。即通过参与你正在下载的Url的一部分或者只是使用随机/临时文件名。

像这样的东西(假设网址是某种IEnumerable<string>

foreach (var item in urls) 
{ 
    var name = item.Substring(item.LastIndexOf('/')).Remove(0, 1); 
    client.DownloadFile(item, "C:\\" + name); 
} 

选项2:使用Parallel.ForEach但改变DownloadFile代码只下载一个文件:

public static void DownloadFile(string url) 
{ 
    WebClient client = new WebClient(); 
    var name = url.Substring(url.LastIndexOf('/')).Remove(0, 1); 
    client.DownloadFile(url, "C:\\" + name); 
} 
+0

正如你可以阅读他的代码,他正在使用一些东西来创建不同的文件名。 – Aidiakapi 2012-07-11 01:50:17

+0

而名称显然是一个变量,这是基于网址。他提供了代码:'var name = url.Substring(url.LastIndexOf('/'))。Remove(0,1);' – Aidiakapi 2012-07-11 01:53:23

+0

@Aidiakapi,明白了......被代码弄糊涂了--OP实际上多次下载相同的文件 - 更新答案... – 2012-07-11 01:53:45