【问题标题】:What is the best way to download files via HTTP using .NET?使用 .NET 通过 HTTP 下载文件的最佳方式是什么?
【发布时间】:2010-03-24 05:09:07
【问题描述】:

在我的一个应用程序中,我使用 WebClient 类从 Web 服务器下载文件。根据 Web 服务器,有时应用程序会下载数百万个文档。似乎当有很多文档时,WebClient 的性能无法很好地扩展。

即使在成功下载特定文档后,WebClient 似乎也不会立即关闭它为 WebServer 打开的连接。

我想知道我还有什么其他选择。

更新: 我还注意到,对于每次下载,WebClient 都会执行身份验证握手。因为我的应用程序只与单个 Web 服务器通信,所以我期待看到这种握手一次。 WebClient 的后续调用不应该重用身份验证会话吗?

更新:我的应用程序还调用了一些 Web 服务方法,并且对于这些 Web 服务调用,似乎重用了身份验证会话。此外,我正在使用 WCF 与 Web 服务进行通信。

【问题讨论】:

  • 您使用的是异步 Web 客户端调用还是同步调用?
  • 我正在使用同步调用,但是多个线程同时调用不同的 WebClient 调用。
  • 我建议只使用一个 Web 客户端和异步调用进行测试,以避免冗余的身份验证阶段。我认为 webclient 不会立即关闭连接是有目的的,因此您可以排队另一个请求。我会将 WebClient 抽象视为 Web 浏览器,在一个启动的 Web 浏览器中,您可以发起多个请求而无需重新验证。但是,如果您每次想要下载文件时关闭浏览器并重新打开另一个浏览器(即使您共享 cookie),它可能会变慢。

标签: c# .net http webclient


【解决方案1】:

我认为您仍然可以使用“WebClient”。但是,您最好使用“使用”块作为一种好习惯。这将确保对象已关闭并被丢弃:-

using(WebClient client = new WebClient()) {
// Use client
} 

【讨论】:

  • 我认为调用 WebClient 的 Dispose 方法并没有什么收获。 Dispose 方法就在那里,因为 WebClient 继承自 Component 类。
  • @Shamika:无论如何都要这样做。如果未来版本决定利用 IDisposable 怎么办?不要依赖实施细节。
【解决方案2】:

我敢打赌,您遇到了每台服务器 2 个连接的默认限制。尝试在程序开头运行此代码:

var cme = new System.Net.Configuration.ConnectionManagementElement();
cme.MaxConnection = 100;
System.Net.ServicePointManager.DefaultConnectionLimit = 100;

【讨论】:

    【解决方案3】:

    我注意到我正在处理的另一个项目中的会话具有相同的行为。为了解决这个“问题”,我确实使用了一个静态 CookieContainer(因为客户端的会话被保存在 cookie 中的值识别)。

    public static class SomeStatics
    { 
        private static CookieContainer _cookieContainer;
        public static CookieContainer CookieContainer
        {
             get
             {
                 if (_cookieContainer == null)
                 {
                     _cookieContainer = new CookieContainer();
                 }
                return _cookieContainer;
             }
        }
    }
    
    public class CookieAwareWebClient : WebClient
    { 
        protected override WebRequest GetWebRequest(Uri address)
        {
            WebRequest request = base.GetWebRequest(address);
            if (request is HttpWebRequest)
            {
                (request as HttpWebRequest).CookieContainer = SomeStatics.CookieContainer;
                (request as HttpWebRequest).KeepAlive = false;
            }
            return request;
        }
    }
    
    //now the code that will download the file
    using(WebClient client = new CookieAwareWebClient())
    {
        client.DownloadFile("http://address.com/somefile.pdf", @"c:\\temp\savedfile.pdf");
    }
    

    代码只是一个示例,灵感来自 Using CookieContainer with WebClient classC# get rid of Connection header in WebClient

    上述代码将在文件下载后立即关闭您的连接并重新使用身份验证。

    【讨论】:

    • 我试过了,但我仍然看到每次下载的 WebClient 身份验证握手。仅供参考,我正在与具有集成 Windows 身份验证的 SharePoint 服务器通信。
    • 怎么样:client.Credentials = new NetworkCredential("username", "password"); ?
    【解决方案4】:

    WebClient 可能是最好的选择。它不会立即关闭连接是有原因的:因此它可以再次使用相同的连接,而无需打开新的连接。如果您发现它没有按预期重用连接,那通常是因为您没有 Close()ing 上一个请求的响应:

    var request = WebRequest.Create("...");
    // populate parameters
    
    var response = request.GetResponse();
    // process response
    
    response.Close(); // <-- make sure you don't forget this!
    

    【讨论】:

    • 我正在使用 WebClient.DownloadData() 来下载内容。不确定我是否需要在这里明确关闭任何响应对象。我想方法 DownloadData 在内部为我做。
    猜你喜欢
    • 2021-03-04
    • 1970-01-01
    • 2023-04-06
    • 2010-11-24
    • 2023-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多