C# 采用HttpWebRequest 、WebClient和HttpClient下载https的文件异常问题

今天有个客户反应,程序下载文件失败,无法正常使用。

远程客户电脑后,查看错误日志,都是提示https:****************************.dll等一系列文件的下载错误提示

提示基础连接已经关闭: 发送时发生错误。

在网上找了很多方案都没有能解决,大多都是https链接时增加指定协议,很遗憾未能解决

        HttpWebRequest request;
            HttpWebResponse response;
            request = (HttpWebRequest)WebRequest.Create(strUrl);
            if (isHttps)
            {
                ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult);
                request.ProtocolVersion = HttpVersion.Version10;

                ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

            }

找不到原因,客户又着急使用,就想着换成WebClient下载类试试,于是写了个粗糙的demo

WebClient webClient = new WebClient();
webClient.DownloadFile(textBox1.Text, Path.GetFileName(textBox1.Text));

发现还是提示同样的错误,这个时候一头雾水,心里万马奔腾

心思不能乱,不行我在换,72般武艺都耍上,于是用HttpClient类,写个demo试试

 using (HttpClient client = new HttpClient())
 {
     // 使用异步方法下载文件
     HttpResponseMessage response = await client.GetAsync(textBox1.Text);
     response.EnsureSuccessStatusCode(); // 确保请求成功

     // 保存文件
     using (FileStream fileStream = File.Create( Path.GetFileName(textBox1.Text)))
     {
         await response.Content.CopyToAsync(fileStream);
     }
 }

发现还是不能下载文件,但是错误提示有变化,提示为“因为算法不同,客户端与服务器无法通信

于是寻找这个错误的解决方案,需要在注册表这个位置将协议值修改下

计算机\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols

 一看客户电脑上,好几个,一个个修改太麻烦,直接将协议改名,让这个设置失效。

在启动测试程序下载文件,发现正常了,完工。

 

后来在网上又发现一个解决方案,感觉可能能行,由于客户问题处理完后,无法在霸占其电脑了,将这个方案记录下,后续遇到在验证,或者有遇到相同问题的天涯沦落人验证后给我留言,谢谢

在工作中要获取一个网络api下的内容,因为要auth认证,本以为很简单

string url="https://.....";
string usernamePassword = CustomerID + ":" + CustomerCertificate;
string basic = Convert.ToBase64String(new ASCIIEncoding().GetBytes(usernamePassword));
HttpWebRequest myReq = (HttpWebRequest)WebRequest.Create(url);
myReq.Headers.Add("Authorization", "Basic " + basic);
HttpWebResponse myRes = (HttpWebResponse)myReq.GetResponse();  //<-- 这里就报错了
Stream resStream = myRes.GetResponseStream();
StreamReader strReader = new StreamReader(resStream);
string resStr = strReader.ReadToEnd();
Console.WriteLine(resStr);

 

结果运行时提示“提示基础连接已经关闭: 发送时发生错误。”
在浏览器下访问网址则正常,刚开始怀疑是basic不对,在浏览器下用同样的值模拟了一下能正常获取,然后把https换成http程序又能正常获取了,定位到问题出在ssl证书上
查了一下资料
添加以下代码

ServicePointManager.Expect100Continue = true;
ServicePointManager.CheckCertificateRevocationList = true;
ServicePointManager.DefaultConnectionLimit = 100;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls; 
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };

 

改回https还是提示原来的异常,换了另外一个https的网址测试却又正常,在浏览器下对比两个https网址的ssl证书,发现能正常访问的测试网址是tls1.0 不能访问的网址是tls1.2
找到问题了,原来在.net4.5以下tls1.2的设置如下

ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072; 
//.net4.5及以上
//ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

再次运行,ok

 

posted @ 2024-02-22 17:51  取经路上  阅读(356)  评论(0编辑  收藏  举报