Jak pobrać plik z adresu URL w C #?

350

Jaki jest prosty sposób pobierania pliku ze ścieżki URL?

Vbroto
źródło
13
Spójrz na System.Net.WebClient
seanb

Odpowiedzi:

475
using (var client = new WebClient())
{
    client.DownloadFile("http://example.com/file/song/a.mpeg", "a.mpeg");
}
Raj Kumar
źródło
24
Najlepsze rozwiązanie w historii, ale chciałbym dodać 1 ważny wiersz „client.Credentials = new NetworkCredential („ UserName ”,„ Password ”);”
Deweloper
3
Powitalny efekt uboczny: Ta metoda obsługuje również pliki lokalne jako pierwszy parametr
oo_dev
Dokument MSDN wspomniał teraz o użyciu HttpClient zamiast tego: docs.microsoft.com/en-us/dotnet/api/…
StormsEngineering
Chociaż myślę, że WebClient wydaje się być znacznie prostszym i prostszym rozwiązaniem.
StormsEngineering
1
@ copa017: Lub niebezpieczny, jeśli na przykład adres URL jest dostarczany przez użytkownika, a kod C # działa na serwerze WWW.
Heinzi,
177

Uwzględnij tę przestrzeń nazw

using System.Net;

Pobierz asynchronicznie i umieść pasek postępu, aby pokazać status pobierania w samym wątku interfejsu użytkownika

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
źródło
14
Pytanie dotyczy najprostszego sposobu. Komplikowanie nie jest najprostsze.
Zagadnienie
75
Większość osób woli pasek postępu podczas pobierania. Właśnie napisałem najprostszy sposób, aby to zrobić. To może nie być odpowiedź, ale spełnia wymagania Stackoverflow. To ma komuś pomóc.
Sayka
3
Jest to tak samo proste jak inna odpowiedź, jeśli po prostu pominiesz pasek postępu. Ta odpowiedź obejmuje także przestrzeń nazw i używa asynchronizacji dla operacji we / wy. Również pytanie nie wymaga najprostszego sposobu, tylko prosty sposób. :)
Josh
Myślę, że lepiej byłoby udzielić 2 odpowiedzi jednej prostej i jednej z paskiem postępu
Jesse de gans
@Jenedegans Istnieje już odpowiedź, która pokazuje, jak po prostu pobierać bez paska postępu. Dlatego napisałem odpowiedź, która pomaga w asynchronicznym pobieraniu i implementacji
paska
75

Użyj 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
źródło
42
using System.Net;

WebClient webClient = new WebClient();
webClient.DownloadFile("http://mysite.com/myfile.txt", @"c:\myfile.txt");
petrzjunior
źródło
33
Witamy w SO! Zasadniczo nie jest dobrym pomysłem zamieszczanie odpowiedzi niskiej jakości na istniejące i stare pytania, które już mają bardzo pozytywne odpowiedzi.
ThiefMaster
28
Znalazłem odpowiedź z komentarza seanb, ale naprawdę wolę tę odpowiedź „niskiej jakości” od innych. Jest kompletny (za pomocą instrukcji), zwięzły i łatwy do zrozumienia. Bycie starym pytaniem nie ma znaczenia, IMHO.
Josh
21
Uważa jednak, że odpowiedź na temat używania jest znacznie lepsza, ponieważ uważam, że WebClient powinien zostać usunięty po użyciu. Umieszczenie go w środku za pomocą zapewnia jego utylizację.
Ricardo Polo Jaramillo,
5
Nie ma to nic wspólnego z utylizacją w tym przykładzie kodu ... Instrukcja using pokazuje po prostu przestrzeń nazw do użycia, nie, że WebClient używa do używania do usuwania ...
cdie
17

Ukończ klasę, aby pobrać plik podczas drukowania statusu na konsolę.

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

Stosowanie:

static void Main(string[] args)
{
    var success = FileDownloader.DownloadFile(fileUrl, fullPathWhereToSave, timeoutInMilliSec);
    Console.WriteLine("Done  - success: " + success);
    Console.ReadLine();
}
Jonas_Hess
źródło
1
Czy możesz wyjaśnić, dlaczego używasz SemaphoreSlimw tym kontekście?
mmushtaq
10

Spróbuj użyć tego:

private void downloadFile(string url)
{
     string file = System.IO.Path.GetFileName(url);
     WebClient cln = new WebClient();
     cln.DownloadFile(url, file);
}
Surendra Shrestha
źródło
gdzie plik zostanie zapisany?
IB
Plik zostanie zapisany w lokalizacji, w której znajduje się plik wykonywalny. Jeśli chcesz uzyskać pełną ścieżkę, użyj pełnej ścieżki wraz z plikiem (który jest nazwą pliku, który chcesz pobrać)
Surendra Shrestha
8

Sprawdź połączenie sieciowe, GetIsNetworkAvailable()aby uniknąć tworzenia pustych plików, gdy nie jest ono podłączone do sieci.

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
źródło
Sugerowałbym, aby nie używać, GetIsNetworkAvailable()ponieważ z mojego doświadczenia zwraca zbyt wiele fałszywych trafień.
Cherona
O ile nie jesteś w sieci komputerowej, takiej jak LAN, GetIsNetworkAvailable()zawsze wróci poprawnie. W takim przypadku możesz użyć System.Net.WebClient().OpenRead(Uri)metody, aby sprawdzić, czy zwraca po otrzymaniu domyślnego adresu URL. Zobacz WebClient.OpenRead ()
haZya
2

Poniższy kod zawiera logikę pobierania pliku o oryginalnej nazwie

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
źródło
1

Konieczne może być sprawdzenie stanu i aktualizacja paska postępu podczas pobierania pliku lub użycie poświadczeń przed wysłaniem żądania.

Oto przykład obejmujący te opcje. Zastosowano notację lambda i interpolację ciągów :

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
źródło
1

Z moich badań wynika, że WebClient.DownloadFileAsyncto najlepszy sposób na pobranie pliku. Jest dostępny w System.Netprzestrzeni nazw i obsługuje również rdzeń .net.

Oto przykładowy kod do pobrania pliku.

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

Z powyższym kodem plik zostanie pobrany w tepdownloadfolderze katalogu projektu. Przeczytaj komentarz w kodzie, aby zrozumieć, co robi powyższy kod.

Kiran Shahi
źródło