C# .NET – pobieranie pliku z serwera HTTP

W jaki sposób w C# zrealizować ściąganie pliku z serwera www? Rozwiązanie jest proste, nawet, zbyt proste :) Oto najkrótszy z możliwych sposobów:

using System.Net;
 
namespace DownloadTest
{
    class Program
    {
        static void Main(string[] args)
        {
            WebClient webClient = new WebClient();
            try
            {
                webClient.DownloadFile("http://server/file", "myFileName");
            }
            catch (WebException e)
            {
                //some error
            }
        }
    }
}

Metoda DownloadFile z klasy webClient przyjmuje dwa parametry: String lub URI z adresem sieciowym pliku oraz String z nazwą pod jaką plik zostanie zapisany lokalnie. Jednak ta metoda jest częściowo nieelegancka – blokuje całkowicie wątek aż do zakończenia pobierania pliku. Nie możemy w tym czasie odebrać żadnych eventów (np. użytkownik nie będzie w stanie przerwać operacji ściągania) ani np. informować o postępie. Zamiast niej możemy jednak użyć podobnej metody – DownloadFileAsync(Uri, String):

using System;
using System.Net;
 
namespace DownloadTest
{
    class Program
    {
        static void Main(string[] args)
        {
            WebClient webClient = new WebClient();
 
            webClient.DownloadFileCompleted += new System.ComponentModel.AsyncCompletedEventHandler(webClient_DownloadFileCompleted);
            webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(webClient_DownloadProgressChanged);
 
            try
            {
                webClient.DownloadFileAsync(new Uri("http://server/file"), "myFileName");
            }
            catch (WebException e)
            {
                //stało się coś bardzo niedobrego ;)
            }
        }
 
        static void webClient_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
        {
            //zobaczmy ile procent pobrano: 
            Console.WriteLine(e.ProgressPercentage.ToString());
        }
 
        static void webClient_DownloadFileCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
        {
            //zakończono pobieranie pliku
        }
    }
}

Warto zapamiętać, że za pomocą DownloadFileAsync nie możemy w jednym wątku ściągać jednocześnie więcej niż jednego pliku – w przypadku próby dokonania takiej operacji otrzymamy wyjątek. Dlatego z pobieraniem kolejnego pliku musimy poczekać do zakończenia pobierania poprzedniego.