Вопрос по webclient, c#, download – Загрузка нескольких файлов WebClient

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());
                }
            }
@GX. Я попробовал это, но не смог заставить его работать вообще :(. Yuki Kutsuya
Ответ здесьstackoverflow.com/questions/6992553/… G-Man
где твой код ломается точно? Вы отлаживали? G-Man
@GX. Ну, он загружает все файлы одновременно и перезаписывает друг друга, так что вы получите 3 поврежденных файла. Yuki Kutsuya

Ваш Ответ

2   ответа
1

который предполагает, что один вызов этой функции загружает все файлы.

Исправления:

Вариант 1: не использоватьParallel.ForEach и просто позвоните в DownloadFile один раз. Укажите уникальные имена файлов для каждой загрузки. То есть принимая участие в загружаемом вами 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);
}
Я полагаю, что так, хотя я все еще не фанат использования раздутогоWebClient для простой загрузки файла: P.
И имя, очевидно, является переменной, которая основана на URL-адресе. Он предоставил код для этого:var name = url.Substring(url.LastIndexOf('/')).Remove(0, 1);
@Aidiakapi, спасибо. Посмотрите, если обновленный ответ отражает ваши комментарии.
Как вы можете прочитать в его коде, он использует что-то для создания другого имени файла.
@Aidiakapi, понял ... был смущен кодом - OP фактически загружает один и тот же файл несколько раз - обновляет ответ ...
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";
@Darkshadw Скорее всего, из-за того, что имена сталкиваются друг с другом, не могли бы вы привести пример URL-адресов и то, как вы хотите, чтобы они отображались (например, я хочу:testurl.com/testfile.html для сопоставления с C: \ testfile.html), тогда я дам вам код. Сейчас я добавил код для добавочного имени файла.
Я нашел скрипт, который делает это, я добавлю его в свой пост, но он тоже не работает :(. Yuki Kutsuya
@Aidiakapi гул ... нет ... WebClient это то, что должно быть использовано здесьmsdn.microsoft.com/en-us/library/… Взгляните на функцию DownloadFile
@GX.WebClient can использоваться для этого, но по сутиWebClient это всего лишь модная обертка вокруг IE.HttpWebRequest с другой стороны, это основное требование для этого.
Когда скрипт загружает файлы, они все повреждены :(. Есть идеи, почему? Yuki Kutsuya

Похожие вопросы