Как программно загрузить большой файл в C # - PullRequest
8 голосов
/ 16 февраля 2010

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

Я знаю о WebClient.DownloadFile (). Но, похоже, нет способа указать определенное количество времени ожидания, чтобы принудительно выйти.

try
{
    WebClient client = new WebClient();
    Uri uri = new Uri(inputFileUrl);
    client.DownloadFile(uri, outputFile);
}
catch (Exception ex)
{
    throw;
}

Другой способ - использовать утилиту командной строки (wget) для загрузки файла и запустить команду с помощью ProcessStartInfo и использовать Process 'WaitForExit (int ms) для принудительного выхода.

ProcessStartInfo startInfo = new ProcessStartInfo();
//set startInfo object

try
{
    using (Process exeProcess = Process.Start(startInfo))
    {
        //wait for time specified
        exeProcess.WaitForExit(1000 * 60 * 60);//wait till 1m

        //check if process has exited
        if (!exeProcess.HasExited)
        {
            //kill process and throw ex
            exeProcess.Kill();
            throw new ApplicationException("Downloading timed out");
        }
    }
}
catch (Exception ex)
{
    throw;
}

Есть ли лучший способ? Пожалуйста помоги. Спасибо.

Ответы [ 4 ]

18 голосов
/ 16 февраля 2010

Используйте WebRequest и получите поток ответов . Затем прочитайте из байтовых блоков потока ответа и запишите каждый блок в файл назначения. Таким образом, вы можете контролировать время остановки, если загрузка занимает слишком много времени, поскольку вы получаете контроль между порциями и можете решить, истекло ли время загрузки на основе часов:

        DateTime startTime = DateTime.UtcNow;
        WebRequest request = WebRequest.Create("http://www.example.com/largefile");
        WebResponse response = request.GetResponse();
        using (Stream responseStream = response.GetResponseStream()) {
            using (Stream fileStream = File.OpenWrite(@"c:\temp\largefile")) { 
                byte[] buffer = new byte[4096];
                int bytesRead = responseStream.Read(buffer, 0, 4096);
                while (bytesRead > 0) {       
                    fileStream.Write(buffer, 0, bytesRead);
                    DateTime nowTime = DateTime.UtcNow;
                    if ((nowTime - startTime).TotalMinutes > 5) {
                        throw new ApplicationException(
                            "Download timed out");
                    }
                    bytesRead = responseStream.Read(buffer, 0, 4096);
                }
            }
        }
7 голосов
/ 16 февраля 2010

Как насчет использования DownloadFileAsync в классе WebClient. Крутая вещь в этом маршруте заключается в том, что вы можете отменить операцию, вызвав CancelAsync, если это займет слишком много времени. В основном, вызовите этот метод, и, если определенное количество времени истекло, вызовите Отмена.

3 голосов
/ 16 февраля 2010

Задано здесь: C #: загрузка URL с таймаутом

Самое простое решение:

public string GetRequest(Uri uri, int timeoutMilliseconds)
{
    var request = System.Net.WebRequest.Create(uri);
    request.Timeout = timeoutMilliseconds;
    using (var response = request.GetResponse())
    using (var stream = response.GetResponseStream())
    using (var reader = new System.IO.StreamReader(stream))
    {
        return reader.ReadToEnd();
    }
}

Лучшее (более гибкое) решение - этот ответ на тот же вопрос в виде WebClientWithTimeout вспомогательного класса.

2 голосов
/ 16 октября 2012

Вы можете использовать DownloadFileAsync, как сказал @BFree, а затем попробовать следующие события WebClient

protected virtual void OnDownloadProgressChanged(DownloadProgressChangedEventArgs e);
protected virtual void OnDownloadFileCompleted(AsyncCompletedEventArgs e);

Тогда вы можете узнать Процент Прогресса

e.ProgressPercentage

Надеюсь, это поможет

...