¿Cómo descargar un archivo desde una URL en C #?

352

¿Cuál es una manera simple de descargar un archivo desde una ruta URL?

vbroto
fuente
13
Eche un vistazo a System.Net.WebClient
seanb

Respuestas:

475
using (var client = new WebClient())
{
    client.DownloadFile("http://example.com/file/song/a.mpeg", "a.mpeg");
}
Raj Kumar
fuente
24
La mejor solución, pero me gustaría agregar 1 línea importante 'client.Credentials = new NetworkCredential ("UserName", "Password");'
Desarrollador
3
Un efecto secundario bienvenido: este método también admite archivos locales como primer parámetro
oo_dev
El documento de MSDN mencionó usar HttpClient ahora en su lugar: docs.microsoft.com/en-us/dotnet/api/…
StormsEngineering el
Aunque creo que WebClient parece una solución mucho más sencilla y sencilla.
Tormentas Ingeniería
1
@ copa017: O uno peligroso, si, por ejemplo, la URL es proporcionada por el usuario y el código C # se ejecuta en un servidor web.
Heinzi
177

Incluir este espacio de nombres

using System.Net;

Descargue asincrónicamente y coloque una barra de progreso para mostrar el estado de la descarga dentro de la interfaz de usuario.

private void BtnDownload_Click(object sender, RoutedEventArgs e)
{
    using (WebClient wc = new WebClient())
    {
        wc.DownloadProgressChanged += wc_DownloadProgressChanged;
        wc.DownloadFileAsync (
            // Param1 = Link of file
            new System.Uri("http://www.sayka.com/downloads/front_view.jpg"),
            // Param2 = Path to save
            "D:\\Images\\front_view.jpg"
        );
    }
}
// Event to track the progress
void wc_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
    progressBar.Value = e.ProgressPercentage;
}
Sayka
fuente
14
La pregunta pide la forma más simple. Hacer más complicado no es hacerlo más simple.
Enigmatividad
75
La mayoría de las personas preferiría una barra de progreso durante la descarga. Así que acabo de escribir la forma más sencilla de hacerlo. Puede que esta no sea la respuesta, pero cumple con el requisito de Stackoverflow. Eso es para ayudar a alguien.
Sayka
3
Esto es tan simple como la otra respuesta si simplemente deja de lado la barra de progreso. Esta respuesta también incluye el espacio de nombres y usa async para E / S. Además, la pregunta no pide la forma más simple, solo una forma simple. :)
Josh el
Creo que sería mejor dar 2 respuestas, una simple y otra con una barra de progreso
Jesse de gans
@Jessedegans Ya hay una respuesta que muestra cómo simplemente descargar sin una barra de progreso. Es por eso que escribí una respuesta que ayuda con la descarga asincrónica y la implementación de la
barra de
76

Uso System.Net.WebClient.DownloadFile:

string remoteUri = "http://www.contoso.com/library/homepage/images/";
string fileName = "ms-banner.gif", myStringWebResource = null;

// Create a new WebClient instance.
using (WebClient myWebClient = new WebClient())
{
    myStringWebResource = remoteUri + fileName;
    // Download the Web resource and save it into the current filesystem folder.
    myWebClient.DownloadFile(myStringWebResource, fileName);        
}
vbroto
fuente
42
using System.Net;

WebClient webClient = new WebClient();
webClient.DownloadFile("http://mysite.com/myfile.txt", @"c:\myfile.txt");
petrzjunior
fuente
33
Bienvenido a SO! En general, no es una buena idea publicar una respuesta de baja calidad a una pregunta existente y antigua que ya tiene respuestas altamente votadas.
ThiefMaster
28
Encontré mi respuesta en el comentario de seanb, pero realmente prefiero esta respuesta de "baja calidad" sobre las otras. Es completo (usando una declaración), conciso y fácil de entender. Ser una vieja pregunta es irrelevante, en mi humilde opinión.
Josh
21
Pero creo que la respuesta con Using es mucho mejor, porque creo que el WebClient debería eliminarse después de usarse. Ponerlo adentro usando garantiza que se elimine.
Ricardo Polo Jaramillo
55
No tiene nada que ver con disponer en este ejemplo de código ... La instrucción using aquí sólo muestran el espacio de nombres para su uso, sin que WebClient es su uso en el uso que disponer ...
CDIE
17

Clase completa para descargar un archivo mientras se imprime el estado en la consola.

using System;
using System.ComponentModel;
using System.IO;
using System.Net;
using System.Threading;

class FileDownloader
{
    private readonly string _url;
    private readonly string _fullPathWhereToSave;
    private bool _result = false;
    private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(0);

    public FileDownloader(string url, string fullPathWhereToSave)
    {
        if (string.IsNullOrEmpty(url)) throw new ArgumentNullException("url");
        if (string.IsNullOrEmpty(fullPathWhereToSave)) throw new ArgumentNullException("fullPathWhereToSave");

        this._url = url;
        this._fullPathWhereToSave = fullPathWhereToSave;
    }

    public bool StartDownload(int timeout)
    {
        try
        {
            System.IO.Directory.CreateDirectory(Path.GetDirectoryName(_fullPathWhereToSave));

            if (File.Exists(_fullPathWhereToSave))
            {
                File.Delete(_fullPathWhereToSave);
            }
            using (WebClient client = new WebClient())
            {
                var ur = new Uri(_url);
                // client.Credentials = new NetworkCredential("username", "password");
                client.DownloadProgressChanged += WebClientDownloadProgressChanged;
                client.DownloadFileCompleted += WebClientDownloadCompleted;
                Console.WriteLine(@"Downloading file:");
                client.DownloadFileAsync(ur, _fullPathWhereToSave);
                _semaphore.Wait(timeout);
                return _result && File.Exists(_fullPathWhereToSave);
            }
        }
        catch (Exception e)
        {
            Console.WriteLine("Was not able to download file!");
            Console.Write(e);
            return false;
        }
        finally
        {
            this._semaphore.Dispose();
        }
    }

    private void WebClientDownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
    {
        Console.Write("\r     -->    {0}%.", e.ProgressPercentage);
    }

    private void WebClientDownloadCompleted(object sender, AsyncCompletedEventArgs args)
    {
        _result = !args.Cancelled;
        if (!_result)
        {
            Console.Write(args.Error.ToString());
        }
        Console.WriteLine(Environment.NewLine + "Download finished!");
        _semaphore.Release();
    }

    public static bool DownloadFile(string url, string fullPathWhereToSave, int timeoutInMilliSec)
    {
        return new FileDownloader(url, fullPathWhereToSave).StartDownload(timeoutInMilliSec);
    }
}

Uso:

static void Main(string[] args)
{
    var success = FileDownloader.DownloadFile(fileUrl, fullPathWhereToSave, timeoutInMilliSec);
    Console.WriteLine("Done  - success: " + success);
    Console.ReadLine();
}
Jonas_Hess
fuente
1
¿Podría explicar por qué está utilizando SemaphoreSlimen este contexto?
mmushtaq
10

Intenta usar esto:

private void downloadFile(string url)
{
     string file = System.IO.Path.GetFileName(url);
     WebClient cln = new WebClient();
     cln.DownloadFile(url, file);
}
Surendra Shrestha
fuente
donde se guardará el archivo?
IB
El archivo se guardará en la ubicación donde está el archivo ejecutable. Si desea la ruta completa, use la ruta completa junto con el archivo (que es el nombre de archivo del elemento que se descargará)
Surendra Shrestha
9

También puede usar el método DownloadFileAsync en la clase WebClient. Descarga en un archivo local el recurso con el URI especificado. Además, este método no bloquea el hilo de llamada.

Muestra:

    webClient.DownloadFileAsync(new Uri("http://www.example.com/file/test.jpg"), "test.jpg");

Para más información:

http://csharpexamples.com/download-files-synchronous-asynchronous-url-c/

turgay
fuente
8

Compruebe si hay una conexión de red GetIsNetworkAvailable()para evitar crear archivos vacíos cuando no está conectado a una red.

if (System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable())
{
    using (System.Net.WebClient client = new System.Net.WebClient())
    {                        
          client.DownloadFileAsync(new Uri("http://www.examplesite.com/test.txt"),
          "D:\\test.txt");
    }                  
}
haZya
fuente
Sugeriría no usarlo GetIsNetworkAvailable(), ya que, en mi experiencia, devuelve demasiados falsos positivos.
Cherona
A menos que esté en una red informática, como una LAN, GetIsNetworkAvailable()siempre volvería correctamente. En tal caso, puede usar el System.Net.WebClient().OpenRead(Uri)método para ver si regresa cuando se le da una URL predeterminada. Ver WebClient.OpenRead ()
haZya
2

El siguiente código contiene lógica para descargar el archivo con el nombre original

private string DownloadFile(string url)
    {

        HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
        string filename = "";
        string destinationpath = Environment;
        if (!Directory.Exists(destinationpath))
        {
            Directory.CreateDirectory(destinationpath);
        }
        using (HttpWebResponse response = (HttpWebResponse)request.GetResponseAsync().Result)
        {
            string path = response.Headers["Content-Disposition"];
            if (string.IsNullOrWhiteSpace(path))
            {
                var uri = new Uri(url);
                filename = Path.GetFileName(uri.LocalPath);
            }
            else
            {
                ContentDisposition contentDisposition = new ContentDisposition(path);
                filename = contentDisposition.FileName;

            }

            var responseStream = response.GetResponseStream();
            using (var fileStream = File.Create(System.IO.Path.Combine(destinationpath, filename)))
            {
                responseStream.CopyTo(fileStream);
            }
        }

        return Path.Combine(destinationpath, filename);
    }
Darshit Gandhi
fuente
1

Es posible que necesite conocer el estado y actualizar una ProgressBar durante la descarga del archivo o usar credenciales antes de realizar la solicitud.

Aquí está, un ejemplo que cubre estas opciones. Se ha utilizado la notación lambda y la interpolación de cadenas :

using System.Net;
// ...

using (WebClient client = new WebClient()) {
    Uri ur = new Uri("http://remotehost.do/images/img.jpg");

    //client.Credentials = new NetworkCredential("username", "password");
    String credentials = Convert.ToBase64String(Encoding.ASCII.GetBytes("Username" + ":" + "MyNewPassword"));
    client.Headers[HttpRequestHeader.Authorization] = $"Basic {credentials}";

    client.DownloadProgressChanged += (o, e) =>
    {
        Console.WriteLine($"Download status: {e.ProgressPercentage}%.");

        // updating the UI
        Dispatcher.Invoke(() => {
            progressBar.Value = e.ProgressPercentage;
        });
    };

    client.DownloadDataCompleted += (o, e) => 
    {
        Console.WriteLine("Download finished!");
    };

    client.DownloadFileAsync(ur, @"C:\path\newImage.jpg");
}
Kreshnik
fuente
1

Según mi investigación, descubrí que WebClient.DownloadFileAsynces la mejor manera de descargar archivos. Está disponible en el System.Netespacio de nombres y también es compatible con .net core.

Aquí está el código de muestra para descargar el archivo.

using System;
using System.IO;
using System.Net;
using System.ComponentModel;

public class Program
{
    public static void Main()
    {
        new Program().Download("ftp://localhost/test.zip");
    }
    public void Download(string remoteUri)
    {
        string FilePath = Directory.GetCurrentDirectory() + "/tepdownload/" + Path.GetFileName(remoteUri); // path where download file to be saved, with filename, here I have taken file name from supplied remote url
        using (WebClient client = new WebClient())
        {
            try
            {
                if (!Directory.Exists("tepdownload"))
                {
                    Directory.CreateDirectory("tepdownload");
                }
                Uri uri = new Uri(remoteUri);
                //password username of your file server eg. ftp username and password
                client.Credentials = new NetworkCredential("username", "password");
                //delegate method, which will be called after file download has been complete.
                client.DownloadFileCompleted += new AsyncCompletedEventHandler(Extract);
                //delegate method for progress notification handler.
                client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(ProgessChanged);
                // uri is the remote url where filed needs to be downloaded, and FilePath is the location where file to be saved
                client.DownloadFileAsync(uri, FilePath);
            }
            catch (Exception)
            {
                throw;
            }
        }
    }
    public void Extract(object sender, AsyncCompletedEventArgs e)
    {
        Console.WriteLine("File has been downloaded.");
    }
    public void ProgessChanged(object sender, DownloadProgressChangedEventArgs e)
    {
        Console.WriteLine($"Download status: {e.ProgressPercentage}%.");
    }
}

Con el código de archivo anterior se descargará dentro de la tepdownloadcarpeta del directorio del proyecto. Lea el comentario en el código para comprender lo que hace el código anterior.

Kiran Shahi
fuente