Как скачать файл с URL в C #?


352

Что такое простой способ загрузки файла по URL-пути?


13
Взгляните на System.Net.WebClient
Seanb

Ответы:


475
using (var client = new WebClient())
{
    client.DownloadFile("http://example.com/file/song/a.mpeg", "a.mpeg");
}

24
Лучшее решение, но я хотел бы добавить 1 важную строку: client.Credentials = new NetworkCredential ("UserName", "Password"); '
Разработчик

3
Приветственный побочный эффект: этот метод также поддерживает локальные файлы в качестве 1-го параметра
oo_dev

Док MSDN упомянул об использовании HttpClient сейчас: docs.microsoft.com/en-us/dotnet/api/…
StormsEngineering

Хотя я думаю, что WebClient кажется гораздо более простым и простым решением.
StormsEngineering

1
@ copa017: или опасный, если, например, URL-адрес предоставлен пользователем, а код C # выполняется на веб-сервере.
Хайнци

177

Включить это пространство имен

using System.Net;

Загрузите асинхронно и поместите ProgressBar, чтобы показать статус загрузки в самой теме пользовательского интерфейса.

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

14
Вопрос просит самый простой способ. Создание более сложного не делает его самым простым.
Загадка

75
Большинство людей предпочли бы индикатор загрузки при загрузке. Поэтому я просто написал самый простой способ сделать это. Это может быть не ответ, но он отвечает требованию Stackoverflow. Это чтобы помочь кому-то.
Сайка

3
Это так же просто, как и другой ответ, если вы просто пропустите индикатор выполнения. Этот ответ также включает пространство имен и использует асинхронный ввод-вывод. Также вопрос не задает самый простой способ, просто простой способ. :)
Джош

Я думаю, что было бы лучше дать 2 ответа: один простой и один с индикатором прогресса
Джесси де Ганс

@Jessedegans Уже есть ответ, который показывает, как просто скачать без индикатора выполнения. Вот почему я написал ответ, который помогает с асинхронной загрузкой и реализацией индикатора выполнения
Sayka

76

Используйте 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);        
}

42
using System.Net;

WebClient webClient = new WebClient();
webClient.DownloadFile("http://mysite.com/myfile.txt", @"c:\myfile.txt");

33
Добро пожаловать на ТАК! Как правило, не очень хорошая идея размещать некачественный ответ на существующий и старый вопрос, на который уже получены ответы с высоким рейтингом.
ThiefMaster

28
Я нашел свой ответ от комментария Seanb, но действительно я предпочитаю этот «некачественный» ответ другим. Это полный (используя утверждение), краткий и легкий для понимания. Быть старым вопросом не имеет значения, ИМХО.
Джош

21
Но он считает, что ответ с использованием намного лучше, потому что, я думаю, WebClient должен быть утилизирован после использования. Помещение его внутрь с помощью гарантирует, что оно будет утилизировано.
Рикардо Поло Харамильо

5
Это не имеет ничего общего с dispose в этом примере кода ... Здесь оператор using просто показывает пространство имен для использования, нет, что WebClient используется для использования для удаления ...
cdie

17

Завершите урок, чтобы загрузить файл во время печати статуса на консоль.

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

Использование:

static void Main(string[] args)
{
    var success = FileDownloader.DownloadFile(fileUrl, fullPathWhereToSave, timeoutInMilliSec);
    Console.WriteLine("Done  - success: " + success);
    Console.ReadLine();
}

1
Пожалуйста, не могли бы вы объяснить, почему вы используете SemaphoreSlimв этом контексте?
mmushtaq

10

Попробуйте использовать это:

private void downloadFile(string url)
{
     string file = System.IO.Path.GetFileName(url);
     WebClient cln = new WebClient();
     cln.DownloadFile(url, file);
}

где файл будет сохранен?
IB

Файл будет сохранен в том месте, где находится исполняемый файл. Если вам нужен полный путь, тогда используйте полный путь вместе с файлом (который является именем файла, который нужно загрузить)
Surendra Shrestha

9

Также вы можете использовать метод DownloadFileAsync в классе WebClient. Он загружает в локальный файл ресурс с указанным URI. Также этот метод не блокирует вызывающий поток.

Образец:

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

Чтобы получить больше информации:

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


8

Проверьте подключение GetIsNetworkAvailable()к сети, используя, чтобы избежать создания пустых файлов, когда не подключен к сети.

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

Я бы предложил не использовать, GetIsNetworkAvailable()поскольку, по моему опыту, возвращает слишком много ложных срабатываний.
Черона

Если вы не находитесь в компьютерной сети, такой как ЛВС, GetIsNetworkAvailable()всегда вернетесь правильно. В таком случае вы можете использовать System.Net.WebClient().OpenRead(Uri)метод, чтобы увидеть, будет ли он возвращаться при задании URL-адреса по умолчанию. См WebClient.OpenRead ()
haZya

2

Ниже приведен код для загрузки файла с оригинальным именем

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

1

Вам может понадобиться узнать статус и обновить ProgressBar во время загрузки файла или использовать учетные данные перед выполнением запроса.

Вот пример, который охватывает эти варианты. Использовалась лямбда-нотация и строковая интерполяция :

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

1

Согласно моему исследованию, я обнаружил, что WebClient.DownloadFileAsyncэто лучший способ загрузить файл. Он доступен в System.Netпространстве имен и поддерживает ядро ​​.net.

Вот пример кода для загрузки файла.

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

С помощью вышеуказанного кода файл будет загружен в tepdownloadпапку каталога проекта. Пожалуйста, прочитайте комментарий в коде, чтобы понять, что делает вышеуказанный код.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.