如何从C#中的URL下载文件?

如何从C#中的URL下载文件?,c#,downloadfile,C#,Downloadfile,从URL路径下载文件的简单方法是什么?使用: 也可以在WebClient类中使用DownloadFileAsync方法。它将具有指定URI的资源下载到本地文件。此外,此方法不会阻止调用线程 样本: webClient.DownloadFileAsync(new Uri("http://www.example.com/file/test.jpg"), "test.jpg"); 有关更多信息: static void Main(string[] args) { var succes

从URL路径下载文件的简单方法是什么?

使用:


也可以在WebClient类中使用DownloadFileAsync方法。它将具有指定URI的资源下载到本地文件。此外,此方法不会阻止调用线程

样本:

    webClient.DownloadFileAsync(new Uri("http://www.example.com/file/test.jpg"), "test.jpg");
有关更多信息:

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

包括此名称空间

using System.Net;
异步下载,并放置一个进度条,以显示UI线程本身内的下载状态

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

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

完成类以在将状态打印到控制台时下载文件。

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

您可能需要在文件下载期间了解状态并更新进度条,或者在发出请求之前使用凭据

这是一个涵盖这些选项的示例Lambda表示法字符串插值已被使用:

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

下面的代码包含使用原始名称下载文件的逻辑

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);
    }
尝试使用以下方法:

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

根据我的研究,我发现这是下载文件的最佳方式。它在
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
文件夹中下载。请阅读代码中的注释以了解上述代码的作用。

如果您需要设置标题Cookies来下载文件,您需要做一些稍微不同的事情。这里有一个例子

并且,要使用此添加所需的标题

private void SetHeaders(HttpClient client)
{
    // TODO: SET ME
    client.DefaultRequestHeaders.Connection.Add("keep-alive");
    client.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) ...");
    client.DefaultRequestHeaders.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9, ...");
    client.DefaultRequestHeaders.AcceptEncoding.Add(new StringWithQualityHeaderValue("gzip"));
    client.DefaultRequestHeaders.AcceptEncoding.Add(new StringWithQualityHeaderValue("deflate"));
    client.DefaultRequestHeaders.AcceptLanguage.Add(new StringWithQualityHeaderValue("en-US"));
    client.DefaultRequestHeaders.AcceptLanguage.Add(new StringWithQualityHeaderValue("en", .9));
    ...
}
旁白:您可以通过以下方式填充CookieContainer:

  • 循环浏览以前响应的cookies。
    • 此响应可能来自HttpAgilityPack、WebClient或puppeter(很多选项)
  • 手动输入(来自配置值或硬编码值)
  • WebClient已过时

    如果要下载到文件中,请使用
    ResponseHeadersRead
    如下方式避免首次读取内存:

    static public async Task HttpDownloadFileAsync(HttpClient httpClient, string url, string fileToWriteTo) {
      using HttpResponseMessage response = await httpClient.GetAsync(url, HttpCompletionOption.ResponseHeadersRead);
      using Stream streamToReadFrom = await response.Content.ReadAsStreamAsync(); 
      using Stream streamToWriteTo = File.Open(fileToWriteTo, FileMode.Create); 
      await streamToReadFrom.CopyToAsync(streamToWriteTo);
    }
    
    static void Main(字符串[]args)
    {
    下载FileAsync().GetAwaiter();
    Console.WriteLine(“文件已下载”);
    Console.Read();
    }
    私有静态异步任务DownloadFileAsync()
    {
    WebClient客户端=新的WebClient();
    等待客户端。下载FileTaskAsync(新Uri(“http://somesite.com/myfile.txt”,“mytxtFile.txt”);
    }
    

    查看System.Net.WebClientWelcome!一般来说,对一个已有的和旧的问题发布一个低质量的答案并不是一个好主意,因为这个问题已经有了高投票率的答案。我从seanb的评论中找到了我的答案,但与其他答案相比,我更喜欢这个“低质量”的答案。它完整(使用语句),简洁易懂。作为一个老问题是不相关的,IMHO。但它认为使用的答案要好得多,因为,我认为WebClient应该在使用后处理。使用将它放在内部可确保它已被处置。在本代码示例中,它与处置无关。。。这里的using语句只是显示要使用的名称空间,没有说明WebClient被用于use to be dispose…问题是最简单的方法。让它变得更复杂并不是让它变得最简单。大多数人在下载时更喜欢一个进度条。所以我写了最简单的方法。这可能不是答案,但它满足Stackoverflow的要求。这是为了帮助某人。如果你不使用进度条,这和另一个答案一样简单。这个答案还包括名称空间,并使用异步进行I/O。另外,这个问题不要求最简单的方法,只要求简单的方法。:)我想给出两个答案,一个简单,一个带进度条better@Jessedegans已经有一个答案显示了如何不用progressbar直接下载。这就是为什么我写了一个答案,帮助异步下载和progressbar实现有史以来最好的解决方案,但我想添加一行重要内容“client.Credentials=new NetworkCredential(“用户名”、“密码”);”一个受欢迎的副作用:此方法还支持本地文件作为第一个参数,尽管我认为WebClient似乎是一个更直接、更简单的解决方案。@copa017:或者是一个危险的解决方案,例如,如果URL是用户提供的,并且C#代码在web服务器上运行。将其设为异步:WebClient=new WebClient();等待client.DownloadFileTaskAsync(新Uri(“),“mytxtFile.txt”);请您解释一下为什么在此上下文中使用
    SemaphoreSlim
    ?文件将保存在哪里?文件将保存在可执行文件所在的位置。如果需要完整路径,请使用完整路径和文件(这是要下载的项目的文件名)我建议不要使用
    GetIsNetworkAvailable()
    ,因为根据我的经验,返回的误报太多。除非您在计算机网络(如LAN)中,
    GetIsNetworkAvailable()
    将始终正确返回。在这种情况下,您可以使用
    System.Net.WebClient().OpenRead(Uri)
    方法,以查看它在给定默认url时是否返回。请参阅有关代码语句用途的一些注释,对于那些不熟悉异步操作和跨线程调用的人来说可能会有所帮助。WebClient已过时请参阅
    // Pass in the HTTPGET URL, Full Path w/Filename, and a populated Cookie Container (optional)
    private async Task DownloadFileRequiringHeadersAndCookies(string getUrl, string fullPath, CookieContainer cookieContainer, CancellationToken cancellationToken)
    {
        cookieContainer ??= new CookieContainer();  // TODO: FILL ME AND PASS ME IN
    
        using (var handler = new HttpClientHandler()
        {
            UseCookies = true,
            CookieContainer = cookieContainer, // This will, both, use the cookies passed in, and update/create cookies from the response
            ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true, // use only if it gets angry about the SSL endpoints
            AllowAutoRedirect = true,
        })
        {
            using (var client = new HttpClient(handler))
            {
                SetHeaders(client);
    
                using (var response = await client.GetAsync(getUrl, cancellationToken))
                {
                    if (response.IsSuccessStatusCode)
                    {
                        var bytes = await response.Content.ReadAsByteArrayAsync(cancellationToken);
                        await File.WriteAllBytesAsync(fullPath, bytes, cancellationToken); // This overwrites the file
                    }
                    else
                    {
                        // TODO: HANDLE ME
                        throw new FileNotFoundException();
                    }
                }
            }
        }
    }
    
    private void SetHeaders(HttpClient client)
    {
        // TODO: SET ME
        client.DefaultRequestHeaders.Connection.Add("keep-alive");
        client.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) ...");
        client.DefaultRequestHeaders.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9, ...");
        client.DefaultRequestHeaders.AcceptEncoding.Add(new StringWithQualityHeaderValue("gzip"));
        client.DefaultRequestHeaders.AcceptEncoding.Add(new StringWithQualityHeaderValue("deflate"));
        client.DefaultRequestHeaders.AcceptLanguage.Add(new StringWithQualityHeaderValue("en-US"));
        client.DefaultRequestHeaders.AcceptLanguage.Add(new StringWithQualityHeaderValue("en", .9));
        ...
    }
    
    static public async Task HttpDownloadFileAsync(HttpClient httpClient, string url, string fileToWriteTo) {
      using HttpResponseMessage response = await httpClient.GetAsync(url, HttpCompletionOption.ResponseHeadersRead);
      using Stream streamToReadFrom = await response.Content.ReadAsStreamAsync(); 
      using Stream streamToWriteTo = File.Open(fileToWriteTo, FileMode.Create); 
      await streamToReadFrom.CopyToAsync(streamToWriteTo);
    }