2012-07-11 188 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