0

複数のファイルをダウンロードしようとしていますが、期待どおりに機能しません。私はたくさんのことを試しましたが、本当にもう何をすべきかわからないので、誰かがこのスクリプトの何が問題になっているのか教えてもらえますか?

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

2 に答える 2

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プロトコルの適切な実装を使用していないためです。これを機能させるには、構成ファイルにこれを追加する必要があります(ASP.Netサイトかオフラインアプリケーションかに応じて、App.configまたはWeb.configのいずれか)。

<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";
于 2012-07-11T01:35:55.997 に答える
1

この関数を1回呼び出すだけですべてのファイルがダウンロードされることを前提として、DownloadFileコード内の同じファイルにすべてのファイルをダウンロードしています。

修正:

オプション1:使用せずParallel.ForEach、DownloadFileを1回呼び出すだけです。ダウンロードごとに一意のファイル名を指定します。つまり、ダウンロードしているUrlに参加するか、単にランダム/一時ファイル名を使用します。

このようなもの(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);
}
于 2012-07-11T01:47:55.613 に答える