Подождите, пока последний файл будет загружен - PullRequest
0 голосов
/ 09 января 2020

У меня есть код для загрузки файлов PDF. Теперь я столкнулся с проблемой, когда выполняю следующую задачу, но загрузка последнего файла еще не завершена. После выполнения моего текущего кода последний файл имеет размер около 650 Мб и должен быть 1300 Мб. Также невозможно открыть его, поскольку он загружен не полностью, и поэтому поврежден.

Процесс не может получить доступ к файлу, поскольку он используется другим процессом.

Как обеспечить загрузку файлов?

            HtmlDocument htmlDoc = new HtmlWeb().Load("http://example.com/");

            // Thread.Sleep(5000); // wait some time

            HtmlNodeCollection ProductListPage = htmlDoc.DocumentNode.SelectNodes("//div[@class='productContain padb6']//div[@class='large-4 medium-4 columns']/a");
            foreach (HtmlNode src in ProductListPage)
            {
                htmlDoc = new HtmlWeb().Load(src.Attributes["href"].Value);

                // Thread.Sleep(5000); // wait some time

                HtmlNodeCollection LinkTester = htmlDoc.DocumentNode.SelectNodes("//div[@class='row padt6 padb4']//a");
                if (LinkTester != null)
                {
                    foreach (var dllink in LinkTester)
                    {
                        string LinkURL = dllink.Attributes["href"].Value;
                        Console.WriteLine(LinkURL);

                        string ExtractFilename = LinkURL.Substring(LinkURL.LastIndexOf("/"));
                        var DLClient = new WebClient();

                        // Thread.Sleep(5000); // wait some time

                        DLClient.DownloadFileAsync(new Uri(LinkURL), @"C:\temp\" + ExtractFilename);
                    }
                }
            }

Мой следующий процесс - переименовать загруженные файлы:

    var files = Directory.GetFiles(@"C:\temp\", "*.pdf");
    // string prefix = "SomePrefix";
    foreach (var file in files)
    {
        string newFileName = Path.Combine(Path.GetDirectoryName(file), file.Replace("-", " "));
        File.Move(file, newFileName);
    }

Переименование проходит гладко, пока не будет загружен последний файл, и это не произойдет. где я получаю сообщение об ошибке.

Я добавил Thread.Sleep(5000); // wait some time между этими двумя, но, возможно, это не лучшее решение, поскольку текущего времени ожидания недостаточно, и оно может изменяться в зависимости от соединения inte rnet?

Вот полный код:

using System;
using System.Net;
using HtmlAgilityPack;
using System.IO;
using System.Threading;


namespace Crawler
{

    class Program
    {
        static void Main(string[] args)
        {

            {
                HtmlDocument htmlDoc = new HtmlWeb().Load("http://example.com");

                // Thread.Sleep(5000); // wait some time

                HtmlNodeCollection ProductListPage = htmlDoc.DocumentNode.SelectNodes("//div[@class='productContain padb6']//div[@class='large-4 medium-4 columns']/a");
                foreach (HtmlNode src in ProductListPage)
                {
                    htmlDoc = new HtmlWeb().Load(src.Attributes["href"].Value);

                    // Thread.Sleep(5000); // wait some time

                    HtmlNodeCollection LinkTester = htmlDoc.DocumentNode.SelectNodes("//div[@class='row padt6 padb4']//a");
                    if (LinkTester != null)
                    {
                        foreach (var dllink in LinkTester)
                        {
                            string LinkURL = dllink.Attributes["href"].Value;
                            Console.WriteLine(LinkURL);

                            string ExtractFilename = LinkURL.Substring(LinkURL.LastIndexOf("/"));
                            var DLClient = new WebClient();

                            // Thread.Sleep(5000); // wait some time

                            DLClient.DownloadFileAsync(new Uri(LinkURL), @"C:\temp\" + ExtractFilename);
                        }
                    }
                }
            }

            Thread.Sleep(5000); // wait some time

            var files = Directory.GetFiles(@"C:\temp\", "*.pdf");
            // string prefix = "SomePrefix";
            foreach (var file in files)
            {
                string newFileName = Path.Combine(Path.GetDirectoryName(file), file.Replace("-", " "));
                File.Move(file, newFileName);
            }


        }


    }

}

Ответы [ 2 ]

2 голосов
/ 09 января 2020

Вы наверняка не хотите использовать WebClient.DownloadFileAsync, но его более новый преемник WebClient.DownloadFileTaskAsync. Это можно использовать следующим образом:

await DLClient.DownloadFileTaskAsync(new Uri(LinkURL), @"C:\temp\" + ExtractFilename);

Это процесс async, поэтому ваш вызывающий метод также должен быть async. Используя await, вы гарантируете, что ваша программа продолжит работу только после завершения загрузки (или сбоя).

1 голос
/ 09 января 2020

Вы должны загрузить и загрузить его асинхронно, а не блокировать текущий поток. Когда вы сделаете это, он освободит поток для вызывающей стороны и вернется к контексту только после завершения загрузки / загрузки *

 htmlDoc = await new HtmlWeb().LoadAsync(src.Attributes["href"].Value);

и

 await DLClient.DownloadFileAsync(new Uri(LinkURL), @"C:\temp\" + ExtractFilename);
...