Aprende a descargar un archivo de la web con C# y WebClient.

Hay varios tipos de archivos que puede descargar desde la web: documentos, imágenes, videos, extensiones, etc. Cualquiera sea su razón (una función de actualización en su aplicación, obtener recursos adicionales, etc.), saber cómo descargar un archivo con C # es imprescindible hoy en día.

Para lograr nuestra tarea, vamos a depender de la Clase WebClient de .NET. WebClient es una abstracción de nivel superior construida sobre HttpWebRequest para simplificar las tareas más comunes.

Antes de continuar, no olvide agregar la declaración de uso requerida para poder descargar archivos usando WebClient en la parte superior de su clase:

using System.Net;

Sincrónicamente

La forma más fácil de descargar un archivo de forma sincronizada (congelará la UI), gracias a la clase WebClient va a ser de 5 líneas:

// Una URL web con una respuesta de archivo
string myWebUrlFile = "https://www.google.com/images/icons/ui/doodle_plus/logo.png";
// Ruta local donde se guardará el archivo
string myLocalFilePath = "C:/users/desktop/logo.png";

using (var client = new WebClient())
{
    client.DownloadFile(myWebUrlFile, myLocalFilePath);
}

Con el ejemplo anterior, debe comprender cómo funciona el método DownloadFile. Sin embargo, depende de ti cómo vas a implementar y refinar el método.

Tenga en cuenta que en nuestro ejemplo usamos la declaración using ya que WebClient implementa IDisposable como una buena práctica.

El siguiente fragmento descargará un archivo en el escritorio con su nombre original (que se recupera incluso de la URL con el getFilenamemétodo):

/// <summary>
/// Descargue un archivo en la ruta del escritorio y guárdelo con el nombre de archivo original.
/// </summary>
private void downloadFile()
{
    string desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
    // Cambie la URL por el valor que desee (un cuadro de texto u otra cosa)
    string url = "https://www.google.com/images/icons/ui/doodle_plus/logo.png";
    // Obtener el nombre de archivo de la URL
    string filename = getFilename(url);

    using (var client = new WebClient())
    {
        client.DownloadFile(url, desktopPath + "/" + filename);
    }

    MessageBox.Show("Download ready");
}

/// <summary>
/// Obtenga el nombre de archivo de una URL web:
/// 
/// www.google.com/image.png -> returns : image.png
/// 
/// </summary>
/// <param name="hreflink"></param>
/// <returns></returns>
private string getFilename(string hreflink)
{
    Uri uri = new Uri(hreflink);
  
    string filename = System.IO.Path.GetFileName(uri.LocalPath);

    return filename; 
}

Para probar el fragmento, simplemente ejecute el downloadFilemétodo con alguna acción, es decir, haga clic en un botón.

Asincrónicamente

Por lo general, normalmente y obviamente no queremos congelar la interfaz de usuario y debería preferir siempre la forma asincrónica (a menos que tenga una excepción en su caso).

En este caso vamos a utilizar el método WebClient.DownloadFileAsync 

/// <summary>
/// Descargue un archivo de forma asincrónica en la ruta del escritorio, muestre el progreso de la descarga y guárdelo con el nombre de archivo original.
/// </summary>
private void downloadFile()
{
    string desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
    // Esto descargará una imagen grande de la web, puede cambiar el valor
    // i.e a textbox : textBox1.Text
    string url ="http://feelgrafix.com/data/wallpaper-hd/Wallpaper-HD-11.jpg"
    string filename = getFilename(url);

    using (WebClient wc = new WebClient())
    {
        wc.DownloadProgressChanged += wc_DownloadProgressChanged;
        wc.DownloadFileCompleted += wc_DownloadFileCompleted;
        wc.DownloadFileAsync(new Uri(url), desktopPath + "/" + filename);
    }
}

/// <summary>
///  Muestra el progreso de la descarga en una barra de progreso.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void wc_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
    // En caso de que no tenga una barra de progreso, registre el valor en su lugar
    // Console.WriteLine(e.ProgressPercentage);
    progressBar1.Value = e.ProgressPercentage;
}

private void wc_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
{
    progressBar1.Value = 0;

    if (e.Cancelled)
    {
        MessageBox.Show("The download has been cancelled");
        return;
    }

    if (e.Error != null) // ¡Tenemos un error! Vuelva a intentarlo unas cuantas veces y luego cancele.
    {
        MessageBox.Show("Se produjo un error al intentar descargar el archivo");
        
        return;
    }

    MessageBox.Show("Archivo descargado correctamente");        
}

Como el método es asincrónico, necesitamos instanciar las devoluciones de llamada correctamente en el método downloadFile.

Para probar el fragmento, agregue una barra de progreso a su formulario y ejecute el downloadFilemétodo con alguna acción, es decir, hacer clic en un botón.

Como beneficio adicional, puede mostrar el total de bytes pendientes del (en bytes) del archivo en el evento DownloadProgressChanged:

private void wc_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
    Console.WriteLine(e.ProgressPercentage + "% | " + e.BytesReceived + " bytes out of " + e.TotalBytesToReceive + " bytes retrieven.");
    // 50% | 5000 bytes out of 10000 bytes retrieven.
}

Cancelar una descarga asincrónica

La posibilidad de cancelar una descarga es un elemento básico importante en el ciclo de vida de la descarga de un archivo.

Para cancelar una descarga de WebClient, solo necesita usar el método CancelAsync del cliente web creado.

WebClient client = new WebClient();

private void downloadFile()
{
   string url = "https://www.google.com/images/icons/ui/doodle_plus/logo.png";
   string myLocalFilePath = "C:/users/desktop/logo.png";

   using (client)
   {
       client.DownloadFileAsync(new Uri(url), myLocalFilePath);
   }
}

private void cancelDownload()
{
   client.CancelAsync();
}

Nota: como es más fácil agregar oyentes en la clase en lugar del método downloadFile, exponemos al cliente en el alcance global para que sea accesible desde los métodos cancelDownload y downloadFile. Para probar el fragmento, simplemente agregue los métodos como acción de un par de botones.

Recuerde, para verificar si se canceló la descarga de un archivo, agregue la  DownloadFileCompleteddevolución de llamada y verifique el event.Cancelledvalor como se muestra en el ejemplo asincrónico.

Conclusión

Independientemente del protocolo (http o https), el archivo se descargará sin ningún tipo de problema (siempre que haya internet) si está permitido y es accesible desde el servidor.

Puede usar un pequeño truco para evitar la creación de archivos vacíos en caso de que no haya Internet disponible usando GetIsNetworkAvailable desde NetworkInterface:

if (System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable())
{
    MessageBox.Show("Internet disponible, proceda con la descarga");
}

Que te diviertas ❤️!


Ingeniero de Software Senior en EPAM Anywhere. Interesado en la programación desde los 14 años, Carlos es un programador autodidacta, fundador y autor de la mayoría de los artículos de Our Code World.

Conviertete en un programador más sociable

Patrocinadores