简体   繁体   English

下载多个文件WebClient

[英]Downloading multiple files WebClient

I'm trying to download multiple files but it's not working as I hoped. 我正在尝试下载多个文件,但无法正常运行。 Can someone tell me what's wrong with this script, because I've tried a lot of things and really don't know what to do anymore. 有人可以告诉我此脚本有什么问题吗,因为我已经尝试了很多事情,而且真的不知道该怎么办。

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());
                }
            }

I would use a System.Net.HttpWebRequest instead. 我会改用System.Net.HttpWebRequest

This is what the code would look like: 代码如下所示:

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);
    }
}

Because the URL you told me in the comment isn't using a proper implementation of the HTTP protocol. 因为您在评论中告诉我的URL没有使用HTTP协议的正确实现。 You'll have to add this to your config file in order for it to work (either App.config or Web.config, depending on if it's an ASP.Net site or offline application): 您必须将其添加到配置文件中才能正常工作(App.config或Web.config,取决于它是ASP.Net站点还是脱机应用程序):

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

As to your problem with names colliding which you said in your comment, this should be resolved by changing your var name = url.Substring(url.LastIndexOf('/')).Remove(0, 1); 至于您在评论中提到的名称冲突问题,应通过更改var name = url.Substring(url.LastIndexOf('/')).Remove(0, 1); into something else. 变成其他东西。

If you want to have an incremental filename, you could use this: 如果要使用增量文件名,则可以使用以下命令:

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

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

You are downloading all files to the same file in your DownloadFile code which assumes single call to this function downloads all files. 您正在将所有文件下载到DownloadFile代码中的同一文件中,该文件假定对该函数的单次调用将下载所有文件。

Fixes: 修正:

Option 1: Don't use Parallel.ForEach and simply call DownloadFile once. 选项1:不要使用Parallel.ForEach而只需调用一次DownloadFile。 Specify unique file names for each download. 为每次下载指定唯一的文件名。 Ie by taking part of Url that you are downloading or simply using random/temporary file names. 也就是说,通过参与要下载的Url或仅使用随机/临时文件名即可。

Something like this (assuming urls is some sort of IEnumerable<string> ) 像这样的东西(假设URL是某种IEnumerable<string>

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

Option 2: Use Parallel.ForEach but change DownloadFile code to download only single file: 选项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);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM