Wie lade ich eine Datei von einer URL in C # herunter?

351

Was ist eine einfache Möglichkeit, eine Datei von einem URL-Pfad herunterzuladen?

vbroto
quelle
13
Werfen Sie einen Blick auf System.Net.WebClient
Seanb

Antworten:

475
using (var client = new WebClient())
{
    client.DownloadFile("http://example.com/file/song/a.mpeg", "a.mpeg");
}
Raj Kumar
quelle
24
Die beste Lösung aller Zeiten, aber ich möchte eine wichtige Zeile hinzufügen: 'client.Credentials = new NetworkCredential ("UserName", "Password");'
Entwickler
3
Ein willkommener Nebeneffekt: Diese Methode unterstützt auch lokale Dateien als 1. Parameter
oo_dev
Das MSDN-Dokument erwähnte, stattdessen HttpClient zu verwenden: docs.microsoft.com/en-us/dotnet/api/…
StormsEngineering
Obwohl ich denke, dass WebClient eine viel einfachere und einfachere Lösung zu sein scheint.
StormsEngineering
1
@ copa017: Oder eine gefährliche, wenn beispielsweise die URL vom Benutzer angegeben wird und der C # -Code auf einem Webserver ausgeführt wird.
Heinzi
177

Fügen Sie diesen Namespace ein

using System.Net;

Asynchron herunterladen und eine ProgressBar einfügen , um den Status des Downloads im UI-Thread selbst anzuzeigen

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
quelle
14
Die Frage fragt nach dem einfachsten Weg. Komplizierter zu machen ist nicht das Einfachste.
Rätselhaftigkeit
75
Die meisten Leute würden beim Herunterladen einen Fortschrittsbalken bevorzugen. Also habe ich einfach den einfachsten Weg geschrieben, das zu tun. Dies ist möglicherweise nicht die Antwort, erfüllt jedoch die Anforderungen von Stackoverflow. Das soll jemandem helfen.
Sayka
3
Dies ist genauso einfach wie die andere Antwort, wenn Sie den Fortschrittsbalken einfach weglassen. Diese Antwort enthält auch den Namespace und verwendet Async für E / A. Auch die Frage fragt nicht nach dem einfachsten Weg, sondern nur nach einem einfachen Weg. :)
Josh
Ich denke, 2 Antworten zu geben, eine einfache und eine mit einem Fortschrittsbalken, wäre besser
Jesse de Gans
@Jessedegans Es gibt bereits eine Antwort, die zeigt, wie man einfach ohne Fortschrittsbalken herunterlädt. Deshalb habe ich eine Antwort geschrieben, die beim asynchronen Download und bei der Implementierung der Fortschrittsleiste hilft
Sayka,
75

Verwendung 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
quelle
42
using System.Net;

WebClient webClient = new WebClient();
webClient.DownloadFile("http://mysite.com/myfile.txt", @"c:\myfile.txt");
petrzjunior
quelle
33
Willkommen bei SO! Im Allgemeinen ist es keine gute Idee, eine Antwort von geringer Qualität auf eine vorhandene und alte Frage zu veröffentlichen, die bereits hoch bewertete Antworten enthält.
ThiefMaster
28
Ich habe meine Antwort aus Seanbs Kommentar gefunden, aber ich bevorzuge diese "minderwertige" Antwort wirklich gegenüber den anderen. Es ist vollständig (mit Aussage), prägnant und leicht zu verstehen. Eine alte Frage zu sein ist irrelevant, IMHO.
Josh
21
Aber ich denke, die Antwort mit Using ist viel besser, weil ich denke, dass der WebClient nach der Verwendung entsorgt werden sollte. Wenn Sie es mit verwenden, wird sichergestellt, dass es entsorgt wird.
Ricardo Polo Jaramillo
5
Es hat nichts mit dispose in diesem Codebeispiel zu tun ... Die using-Anweisung hier zeigt nur den zu verwendenden Namespace, nein, dass WebClient verwendet wird, um entsorgt zu werden ...
cdie
17

Schließen Sie die Klasse ab, um eine Datei herunterzuladen, während Sie den Status auf die Konsole drucken.

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);
    }
}

Verwendungszweck:

static void Main(string[] args)
{
    var success = FileDownloader.DownloadFile(fileUrl, fullPathWhereToSave, timeoutInMilliSec);
    Console.WriteLine("Done  - success: " + success);
    Console.ReadLine();
}
Jonas_Hess
quelle
1
Könnten Sie bitte erklären, warum Sie SemaphoreSlimin diesem Zusammenhang verwenden?
mmushtaq
10

Versuchen Sie Folgendes:

private void downloadFile(string url)
{
     string file = System.IO.Path.GetFileName(url);
     WebClient cln = new WebClient();
     cln.DownloadFile(url, file);
}
Surendra Shrestha
quelle
Wo wird die Datei gespeichert?
IB
Die Datei wird an dem Speicherort gespeichert, an dem sich die ausführbare Datei befindet. Wenn Sie den vollständigen Pfad möchten, verwenden Sie den vollständigen Pfad zusammen mit der Datei (dies ist der Dateiname des herunterzuladenden Elements)
Surendra Shrestha
9

Sie können auch die DownloadFileAsync-Methode in der WebClient-Klasse verwenden. Die Ressource mit dem angegebenen URI wird in eine lokale Datei heruntergeladen. Auch diese Methode blockiert den aufrufenden Thread nicht.

Stichprobe:

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

Für mehr Informationen:

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

Turgay
quelle
8

Suchen Sie nach einer Netzwerkverbindung GetIsNetworkAvailable(), um zu vermeiden, dass leere Dateien erstellt werden, wenn keine Verbindung zu einem Netzwerk besteht.

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
quelle
Ich würde nicht vorschlagen verwenden, GetIsNetworkAvailable()da meiner Erfahrung nach zu viele Fehlalarme zurückgegeben werden.
Cherona
Wenn Sie sich nicht in einem Computernetzwerk wie einem LAN befinden, wird GetIsNetworkAvailable()immer korrekt zurückgegeben. In einem solchen Fall können Sie mithilfe der System.Net.WebClient().OpenRead(Uri)Methode überprüfen, ob sie bei Angabe einer Standard-URL zurückgegeben wird. Siehe WebClient.OpenRead ()
haZya
2

Der folgende Code enthält eine Logik zum Herunterladen der Datei mit dem ursprünglichen Namen

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
quelle
1

Möglicherweise müssen Sie den Status kennen und eine ProgressBar während des Herunterladens der Datei aktualisieren oder Anmeldeinformationen verwenden, bevor Sie die Anforderung stellen können.

Hier ist ein Beispiel, das diese Optionen abdeckt. Lambda-Notation und String-Interpolation wurden verwendet:

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
quelle
1

Nach meinen Recherchen habe ich festgestellt, dass dies WebClient.DownloadFileAsyncder beste Weg ist, um Dateien herunterzuladen. Es ist verfügbar inSystem.Net Namespace und unterstützt auch den .net-Kern.

Hier ist der Beispielcode zum Herunterladen der Datei.

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}%.");
    }
}

Mit dem obigen Code wird die Datei im tepdownloadOrdner des Projektverzeichnisses heruntergeladen . Bitte lesen Sie den Kommentar im Code, um zu verstehen, was der obige Code tut.

Kiran Shahi
quelle