using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; using System.Net.Security; using System.Security.Cryptography.X509Certificates; using System.Text; namespace POSV.Utils { /// /// HTTP 请求工具类 /// public static class RequestUtility { #region 代理 private static WebProxy _webproxy = null; /// /// 设置Web代理 /// /// /// /// /// public static void SetHttpProxy(string host , string port , string username , string password) { ICredentials cred; cred = new NetworkCredential(username , password); if (!string.IsNullOrEmpty(host)) { _webproxy = new WebProxy(host + ":" + port ?? "80" , true , null , cred); } } /// /// 清除Web代理状态 /// public static void RemoveHttpProxy() { _webproxy = null; } #endregion #region 同步方法 #region Get /// /// 使用Get方法获取字符串结果(没有加入Cookie) /// /// /// public static string HttpGet(string url , Encoding encoding = null) { WebClient wc = new WebClient(); wc.Proxy = _webproxy; wc.Encoding = encoding ?? Encoding.UTF8; return wc.DownloadString(url); } /// /// 使用Get方法获取字符串结果(加入Cookie) /// /// /// /// /// 证书,如果不需要则保留null /// /// public static string HttpGet(string url , CookieContainer cookieContainer = null , Encoding encoding = null , X509Certificate2 cer = null , int timeOut = Constant.TIMEOUT) { HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); request.Method = "GET"; request.Timeout = timeOut; request.Proxy = _webproxy; if (cer != null) { request.ClientCertificates.Add(cer); } if (cookieContainer != null) { request.CookieContainer = cookieContainer; } HttpWebResponse response = (HttpWebResponse)request.GetResponse(); if (cookieContainer != null) { response.Cookies = cookieContainer.GetCookies(response.ResponseUri); } using (Stream responseStream = response.GetResponseStream()) { using (StreamReader myStreamReader = new StreamReader(responseStream , encoding ?? Encoding.GetEncoding("utf-8"))) { string retString = myStreamReader.ReadToEnd(); return retString; } } } #endregion #region Post /// /// 使用Post方法获取字符串结果,常规提交 /// /// public static string HttpPost(string url , CookieContainer cookieContainer = null , Dictionary formData = null , Encoding encoding = null , X509Certificate2 cer = null , int timeOut = Constant.TIMEOUT) { MemoryStream ms = new MemoryStream(); formData.FillFormDataStream(ms);//填充formData return HttpPost(url , cookieContainer , ms , null , null , encoding , cer , timeOut); } /// /// 使用Post方法获取字符串结果 /// /// /// /// /// 需要上传的文件,Key:对应要上传的Name,Value:本地文件名 /// /// 证书,如果不需要则保留null /// /// 验证服务器证书回调自动验证 /// /// public static string HttpPost(string url , CookieContainer cookieContainer = null , Stream postStream = null , Dictionary fileDictionary = null , string refererUrl = null , Encoding encoding = null , X509Certificate2 cer = null , int timeOut = Constant.TIMEOUT , bool checkValidationResult = false) { HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); request.Method = "POST"; request.Timeout = timeOut; request.Proxy = _webproxy; if (cer != null) { request.ClientCertificates.Add(cer); } if (checkValidationResult) { ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult); } #region 处理Form表单文件上传 var formUploadFile = fileDictionary != null && fileDictionary.Count > 0;//是否用Form上传文件 if (formUploadFile) { //通过表单上传文件 postStream = postStream ?? new MemoryStream(); string boundary = "----" + DateTime.Now.Ticks.ToString("x"); //byte[] boundarybytes = Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n"); string fileFormdataTemplate = "\r\n--" + boundary + "\r\nContent-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: application/octet-stream\r\n\r\n"; string dataFormdataTemplate = "\r\n--" + boundary + "\r\nContent-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}"; foreach (var file in fileDictionary) { try { var fileName = file.Value; //准备文件流 using (var fileStream = FileHelper.GetFileStream(fileName)) { string formdata = null; if (fileStream != null) { //存在文件 formdata = string.Format(fileFormdataTemplate , file.Key , /*fileName*/ Path.GetFileName(fileName)); } else { //不存在文件或只是注释 formdata = string.Format(dataFormdataTemplate , file.Key , file.Value); } //统一处理 var formdataBytes = Encoding.UTF8.GetBytes(postStream.Length == 0 ? formdata.Substring(2 , formdata.Length - 2) : formdata);//第一行不需要换行 postStream.Write(formdataBytes , 0 , formdataBytes.Length); //写入文件 if (fileStream != null) { byte[] buffer = new byte[1024]; int bytesRead = 0; while ((bytesRead = fileStream.Read(buffer , 0 , buffer.Length)) != 0) { postStream.Write(buffer , 0 , bytesRead); } } } } catch (Exception ex) { throw ex; } } //结尾 var footer = Encoding.UTF8.GetBytes("\r\n--" + boundary + "--\r\n"); postStream.Write(footer , 0 , footer.Length); request.ContentType = string.Format("multipart/form-data; boundary={0}" , boundary); } else { request.ContentType = "application/x-www-form-urlencoded"; } #endregion request.ContentLength = postStream != null ? postStream.Length : 0; request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"; request.KeepAlive = true; if (!string.IsNullOrEmpty(refererUrl)) { request.Referer = refererUrl; } request.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36"; if (cookieContainer != null) { request.CookieContainer = cookieContainer; } #region 输入二进制流 if (postStream != null) { postStream.Position = 0; //直接写入流 Stream requestStream = request.GetRequestStream(); byte[] buffer = new byte[1024]; int bytesRead = 0; while ((bytesRead = postStream.Read(buffer , 0 , buffer.Length)) != 0) { requestStream.Write(buffer , 0 , bytesRead); } //debug //postStream.Seek(0, SeekOrigin.Begin); //StreamReader sr = new StreamReader(postStream); //var postStr = sr.ReadToEnd(); postStream.Close();//关闭文件访问 } #endregion HttpWebResponse response = (HttpWebResponse)request.GetResponse(); if (cookieContainer != null) { response.Cookies = cookieContainer.GetCookies(response.ResponseUri); } using (Stream responseStream = response.GetResponseStream()) { using (StreamReader myStreamReader = new StreamReader(responseStream , encoding ?? Encoding.GetEncoding("utf-8"))) { string retString = myStreamReader.ReadToEnd(); return retString; } } } /// /// 使用Post方法获取字符串结果 /// /// /// /// /// 需要上传的文件,Key:对应要上传的Name,Value:本地文件名 /// /// 证书,如果不需要则保留null /// /// 验证服务器证书回调自动验证 /// /// public static string HttpPostCCB(string url, CookieContainer cookieContainer = null, Stream postStream = null, Dictionary fileDictionary = null, string refererUrl = null, Encoding encoding = null, X509Certificate2 cer = null, int timeOut = Constant.TIMEOUT, bool checkValidationResult = false) { HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); request.Method = "POST"; request.Timeout = timeOut; request.Proxy = _webproxy; if (cer != null) { request.ClientCertificates.Add(cer); } if (checkValidationResult) { ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult); } #region 处理Form表单文件上传 var formUploadFile = fileDictionary != null && fileDictionary.Count > 0;//是否用Form上传文件 if (formUploadFile) { //通过表单上传文件 postStream = postStream ?? new MemoryStream(); string boundary = "----" + DateTime.Now.Ticks.ToString("x"); //byte[] boundarybytes = Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n"); string fileFormdataTemplate = "\r\n--" + boundary + "\r\nContent-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: application/octet-stream\r\n\r\n"; string dataFormdataTemplate = "\r\n--" + boundary + "\r\nContent-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}"; foreach (var file in fileDictionary) { try { var fileName = file.Value; //准备文件流 using (var fileStream = FileHelper.GetFileStream(fileName)) { string formdata = null; if (fileStream != null) { //存在文件 formdata = string.Format(fileFormdataTemplate, file.Key, /*fileName*/ Path.GetFileName(fileName)); } else { //不存在文件或只是注释 formdata = string.Format(dataFormdataTemplate, file.Key, file.Value); } //统一处理 var formdataBytes = Encoding.UTF8.GetBytes(postStream.Length == 0 ? formdata.Substring(2, formdata.Length - 2) : formdata);//第一行不需要换行 postStream.Write(formdataBytes, 0, formdataBytes.Length); //写入文件 if (fileStream != null) { byte[] buffer = new byte[1024]; int bytesRead = 0; while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0) { postStream.Write(buffer, 0, bytesRead); } } } } catch (Exception ex) { throw ex; } } //结尾 var footer = Encoding.UTF8.GetBytes("\r\n--" + boundary + "--\r\n"); postStream.Write(footer, 0, footer.Length); request.ContentType = string.Format("multipart/form-data; boundary={0}", boundary); } else { request.ContentType = "application/x-www-form-urlencoded"; } #endregion request.ContentLength = postStream != null ? postStream.Length : 0; request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"; request.KeepAlive = false; request.ProtocolVersion = new Version(1, 0); if (!string.IsNullOrEmpty(refererUrl)) { request.Referer = refererUrl; } request.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36"; if (cookieContainer != null) { request.CookieContainer = cookieContainer; } #region 输入二进制流 if (postStream != null) { postStream.Position = 0; //直接写入流 Stream requestStream = request.GetRequestStream(); byte[] buffer = new byte[1024]; int bytesRead = 0; while ((bytesRead = postStream.Read(buffer, 0, buffer.Length)) != 0) { requestStream.Write(buffer, 0, bytesRead); } //debug //postStream.Seek(0, SeekOrigin.Begin); //StreamReader sr = new StreamReader(postStream); //var postStr = sr.ReadToEnd(); postStream.Close();//关闭文件访问 } #endregion HttpWebResponse response = (HttpWebResponse)request.GetResponse(); if (cookieContainer != null) { response.Cookies = cookieContainer.GetCookies(response.ResponseUri); } using (Stream responseStream = response.GetResponseStream()) { using (StreamReader myStreamReader = new StreamReader(responseStream, encoding ?? Encoding.GetEncoding("GB18030"))) { string retString = myStreamReader.ReadToEnd(); return retString; } } } #endregion /// /// 验证服务器证书 /// /// /// /// /// /// private static bool CheckValidationResult(object sender , X509Certificate certificate , X509Chain chain , SslPolicyErrors errors) { return true; } #endregion /// /// 组装QueryString的方法 /// 参数之间用&连接,首位没有符号,如:a=1&b=2&c=3 /// /// /// public static string GetQueryString(this Dictionary formData) { if (formData == null || formData.Count == 0) { return ""; } StringBuilder sb = new StringBuilder(); var i = 0; foreach (var kv in formData) { i++; sb.AppendFormat("{0}={1}" , kv.Key , kv.Value); if (i < formData.Count) { sb.Append("&"); } } return sb.ToString(); } /// /// 填充表单信息的Stream /// /// /// public static void FillFormDataStream(this Dictionary formData , Stream stream) { string dataString = GetQueryString(formData); var formDataBytes = formData == null ? new byte[0] : Encoding.UTF8.GetBytes(dataString); stream.Write(formDataBytes , 0 , formDataBytes.Length); stream.Seek(0 , SeekOrigin.Begin);//设置指针读取位置 } /// /// 将 URL 中的参数名称/值编码为合法的格式。 /// 可以解决类似这样的问题:假设参数名为 tvshow, 参数值为 Tom&Jerry,如果不编码,可能得到的网址: http://a.com/?tvshow=Tom&Jerry&year=1965 编码后则为:http://a.com/?tvshow=Tom%26Jerry&year=1965 /// 实践中经常导致问题的字符有:'&', '?', '=' 等 /// /// /// public static string AsUrlData(this string data) { if (data == null) { return null; } return Uri.EscapeDataString(data); } } }