9102年了,彙總下HttpClient問題,封印一個
阿新 • • 發佈:2019-01-09
如果找的是core的HttpClientFactory 出門右轉。
-
官方寫法,高併發下,TCP連線不能快速釋放,導致端口占完,無法連線
Dispose 不是馬上關閉tcp連線
主動關閉的一方為什麼不能馬上close而是進入timewait狀態:TCP四次揮手客戶端關閉連結為什麼要等待2倍MSL
正確寫法一個域(一個地址) 保證一個靜態httpclient操作,保證重用tcp連線。
-
如果HttpClient唯一,如果請求頭內容需要變化怎麼辦,異常:"集合已修改;可能無法執行列舉操作"
HttpClient有個介面SendAsync。看
這個方法可以允許使用者傳遞HttpRequestMessage,內部包含(HttpRequestHeaders)
-
HttpClient 死鎖
關於Task同步上下文 造成死鎖問題就不多解釋。避免方法就是ConfigureAwait(false)或者await always。最好是await always。傳送門
說下不用await 而使用類似HttpClient.GetStringAsync(uri).Result 直接同步獲取為什麼沒有死鎖
因為HttpClient原始碼裡面用到async await的地方几乎都加了ConfigureAwait(false)。233333
-
預熱和長連線
其實這是嘴巴dudu園長大人在很久以前就做分析過 傳送門
-
HttpClient 利用stream和json.net 減少記憶體開銷,加快反序列化過程
我們一般的請求流程:發起請求,獲取返回的string物件,然後反序列化成我們想要的物件。而其實可以利用stream直接反序列化成我們想要的物件。
而且可以是在HttpCompletionOption.ResponseHeadersRead的情況下。
HttpClient封印:
1 public class HttpAsyncSender 2 { 3 private static readonly ILogger Logger = LoggerManager.GetLogger(typeof(HttpAsyncSender)); 4 //靜態 重用tcp連線 長連線(not dispose)https://aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/ 5 private static readonly HttpClient HttpClient = new HttpClient(); 6 7 public HttpAsyncSender(Uri baseUri, int timeoutSeconds = 0, bool keepAlive = true, bool preheating = false, long maxResponseContentBufferSize = 0) 8 { 9 //基礎地址 10 HttpClient.BaseAddress = baseUri; 11 //超時 12 if (timeoutSeconds != 0) 13 { 14 HttpClient.Timeout = TimeSpan.FromSeconds(timeoutSeconds); 15 } 16 //response最大接收位元組 預設2gbmstsc 17 if (maxResponseContentBufferSize != 0) 18 { 19 HttpClient.MaxResponseContentBufferSize = maxResponseContentBufferSize; 20 } 21 //長連線 //https://www.cnblogs.com/lori/p/7692152.html http 1.1 default set keep alive 22 if (keepAlive) 23 { 24 HttpClient.DefaultRequestHeaders.Connection.Add("keep-alive"); 25 } 26 //httpclient 預熱 the first request //https://www.cnblogs.com/dudu/p/csharp-httpclient-attention.html 27 if (preheating) 28 { 29 HttpClient.SendAsync(new HttpRequestMessage 30 { 31 Method = new HttpMethod("HEAD"), 32 RequestUri = new Uri(baseUri + "/") 33 }).Result.EnsureSuccessStatusCode(); 34 } 35 } 36 37 #region 非同步 38 39 /// <summary> 40 /// GetAsync 注意 await always 41 /// </summary> 42 /// <param name="url"></param> 43 /// <param name="cancellationToken"></param> 44 /// <returns></returns> 45 public async Task<T> GetAsync<T>(string url, CancellationToken cancellationToken) 46 { 47 try 48 { 49 //https://johnthiriet.com/efficient-api-calls/ 減少記憶體開銷 利用stream特性 加快反序列化 50 using (var request = new HttpRequestMessage(HttpMethod.Get, url)) 51 { 52 var res = await SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); 53 var resStesam = await res.Content.ReadAsStreamAsync().ConfigureAwait(false); 54 if (res.IsSuccessStatusCode) 55 { 56 return DeserializeJsonFromStream<T>(resStesam); 57 } 58 var resStr = await StreamToStringAsync(resStesam).ConfigureAwait(false); 59 Logger.Error($"HttpAsyncSender, GetAsync ,response fail StatusCode:{res.StatusCode} resStr:{resStr} BaseAddress:{HttpClient.BaseAddress},Url:{url}"); 60 } 61 } 62 catch (JsonSerializationException je) 63 { 64 Logger.Error($"HttpAsyncSender,GetAsync JsonSerializationException,BaseAddress:{HttpClient.BaseAddress},Url:{url},je:{je.Message}"); 65 throw; 66 } 67 catch (AggregateException ae) 68 { 69 Logger.Error($"HttpAsyncSender,GetAsync AggregateException,BaseAddress:{HttpClient.BaseAddress},Url:{url} ae:{ae.Flatten()}"); 70 throw; 71 72 } 73 catch (Exception e) 74 { 75 Logger.Error($"HttpAsyncSender,GetAsync Exception,BaseAddress:{HttpClient.BaseAddress},Url:{url},ex:{e.Message}"); 76 throw; 77 } 78 79 return default(T); 80 } 81 82 /// <summary> 83 /// PostAsync 注意 await always 84 /// </summary> 85 /// <param name="url"></param> 86 /// <param name="content"></param> 87 /// <param name="cancellationToken"></param> 88 /// <returns></returns> 89 public async Task<TRes> PostAsync<TReq, TRes>(string url, TReq content, CancellationToken cancellationToken) 90 { 91 try 92 { 93 //https://johnthiriet.com/efficient-api-calls/ 減少記憶體開銷 利用stream特性 加快反序列化 94 using (var request = new HttpRequestMessage(HttpMethod.Post, url)) 95 using (var httpContent = CreateHttpContent(content)) 96 { 97 request.Content = httpContent; 98 var res = await SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); 99 var resStesam = await res.Content.ReadAsStreamAsync().ConfigureAwait(false); 100 if (res.IsSuccessStatusCode) 101 { 102 return DeserializeJsonFromStream<TRes>(resStesam); 103 } 104 var resStr = await StreamToStringAsync(resStesam).ConfigureAwait(false); 105 Logger.Error($"HttpAsyncSender, PostAsync ,response fail StatusCode:{res.StatusCode} resStr:{resStr} BaseAddress:{HttpClient.BaseAddress},Url:{url}"); 106 } 107 } 108 catch (JsonSerializationException je) 109 { 110 Logger.Error($"HttpAsyncSender,PostAsync JsonSerializationException,BaseAddress:{HttpClient.BaseAddress},Url:{url},je:{je.Message}"); 111 throw; 112 } 113 catch (AggregateException ae) 114 { 115 Logger.Error($"HttpAsyncSender,PostAsync AggregateException,BaseAddress:{HttpClient.BaseAddress},Url:{url} ae:{ae.Flatten()}"); 116 throw; 117 118 } 119 catch (Exception e) 120 { 121 Logger.Error($"HttpAsyncSender,PostAsync Exception,BaseAddress:{HttpClient.BaseAddress},Url:{url},ex:{e.Message}"); 122 throw; 123 } 124 125 return default(TRes); 126 } 127 128 /// <summary> 129 /// SendAsync 注意 await always 當需要動態改變request head的時候 呼叫此方法。 解決 "集合已修改;可能無法執行列舉操作" 130 /// </summary> 131 /// <param name="httpRequestMessage"></param> 132 /// <param name="completionOption"></param> 133 /// <param name="cancellationToken"></param> 134 /// <returns></returns> 135 public async Task<HttpResponseMessage> SendAsync(HttpRequestMessage httpRequestMessage, HttpCompletionOption completionOption, CancellationToken cancellationToken) 136 { 137 try 138 { 139 return await HttpClient.SendAsync(httpRequestMessage, completionOption, cancellationToken).ConfigureAwait(false); 140 } 141 catch (AggregateException ae) 142 { 143 Logger.Error( 144 $"HttpAsyncSender,SendAsync AggregateException,BaseAddress:{HttpClient.BaseAddress},Url:{httpRequestMessage.RequestUri} ae:{ae.Flatten()}"); 145 throw; 146 147 } 148 catch (Exception e) 149 { 150 Logger.Error($"HttpAsyncSender,SendAsync Exception,BaseAddress:{HttpClient.BaseAddress},Url:{httpRequestMessage.RequestUri},ex:{e.Message}"); 151 throw; 152 } 153 } 154 155 #endregion 156 157 158 private static T DeserializeJsonFromStream<T>(Stream stream) 159 { 160 if (stream == null || stream.CanRead == false) 161 return default(T); 162 163 using (var sr = new StreamReader(stream)) 164 using (var jtr = new JsonTextReader(sr)) 165 { 166 var js = new JsonSerializer(); 167 var searchResult = js.Deserialize<T>(jtr); 168 return searchResult; 169 } 170 } 171 172 private static async Task<string> StreamToStringAsync(Stream stream) 173 { 174 string content = null; 175 176 if (stream != null) 177 using (var sr = new StreamReader(stream)) 178 content = await sr.ReadToEndAsync(); 179 180 return content; 181 } 182 183 public static void SerializeJsonIntoStream(object value, Stream stream) 184 { 185 using (var sw = new StreamWriter(stream, new UTF8Encoding(false), 1024, true)) 186 using (var jtw = new JsonTextWriter(sw) { Formatting = Formatting.None }) 187 { 188 var js = new JsonSerializer(); 189 js.Serialize(jtw, value); 190 jtw.Flush(); 191 } 192 } 193 194 private static HttpContent CreateHttpContent<T>(T content) 195 { 196 HttpContent httpContent = null; 197 if (content != null) 198 { 199 var ms = new MemoryStream(); 200 SerializeJsonIntoStream(content, ms); 201 ms.Seek(0, SeekOrigin.Begin); 202 httpContent = new StreamContent(ms); 203 httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/json"); 204 } 205 206 return httpContent; 207 } 208 }View Code
HttpWebRequest封印
1 public class HttpSyncSender 2 { 3 private static readonly int DefaultConnectionLimit = 100; 4 private static readonly ILogger Logger = LoggerManager.GetLogger(typeof(HttpSyncSender)); 5 6 static HttpSyncSender() 7 { 8 ServicePointManager.DefaultConnectionLimit = DefaultConnectionLimit; 9 ServicePointManager.UseNagleAlgorithm = false; 10 ServicePointManager.MaxServicePointIdleTime = 500 * 1000; 11 } 12 13 public static void SetDefaultConnectionLimit(int connectionLimit) 14 { 15 ServicePointManager.DefaultConnectionLimit = connectionLimit; 16 } 17 18 #region 同步 HttpWebRequest 19 20 /// <summary> 21 /// 同步傳送POST請求 預設表單提交方式 22 /// </summary> 23 /// <typeparam name="T">T型別</typeparam> 24 /// <param name="url">URL</param> 25 /// <param name="formData">POST資料</param> 26 /// <param name="type">返回值型別:JSON、XML</param> 27 /// <param name="timeout">超時時間(單位:毫秒)</param> 28 /// <param name="headers">請求頭</param> 29 /// <param name="contentType">內容型別 預設"application/x-www-form-urlencoded"</param> 30 /// <param name="referer">來源</param> 31 /// <param name="proxyUrl">代理地址</param> 32 /// <returns>T型別例項</returns> 33 public static T HttpPost<T>(string url, EnumRequestType type, NameValueCollection formData, int timeout, NameValueCollection headers, string contentType = "application/x-www-form-urlencoded", string referer = "", string proxyUrl = null) where T : new() 34 { 35 T t = default(T); 36 HttpWebRequest webrequest = null; 37 var headerStr = headers == null ? string.Empty : JsonConvert.SerializeObject(headers); 38 try 39 { 40 webrequest = (HttpWebRequest)WebRequest.Create(url); 41 webrequest.Method = "POST"; 42 webrequest.UserAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.2; zh-CN; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3 GTB5"; 43 webrequest.AllowAutoRedirect = true; 44 webrequest.Timeout = timeout; 45 SetRequest(webrequest, true, proxyUrl); 46 47 if (headers != null) 48 { 49 foreach (var item in headers.Keys) 50 { 51 webrequest.Headers.Add(item.ToString(), Convert.ToString(headers[item.ToString()])); 52 } 53 } 54 byte[] byteArray = Encoding.UTF8.GetBytes(CreateForm(formData)); 55 webrequest.ContentType = contentType; 56 webrequest.ContentLength = byteArray.Length; 57 if (!string.IsNullOrWhiteSpace(referer)) 58 { 59 webrequest.Referer = referer; 60 } 61 using (var dataStream = webrequest.GetRequestStream()) 62 { 63 dataStream.Write(byteArray, 0, byteArray.Length); 64 } 65 66 using (var webResponse = (HttpWebResponse)webrequest.GetResponse()) 67 { 68 using (var resStream = UnzipStream(webResponse)) 69 { 70 var sr = new StreamReader(resStream, Encoding.UTF8); 71 var result = sr.ReadToEnd(); 72 if (webResponse.StatusCode == HttpStatusCode.OK && !string.IsNullOrEmpty(result)) 73 { 74 t = CreateInstance<T>(result, type); 75 } 76 else 77 { 78 Logger.Error($"HttpSyncSender, Post,返回異常:{webResponse.StatusCode} result:{result} ,Url:{url},cotentType:{contentType} formData:{JsonConvert.SerializeObject(formData)},header:{headerStr}"); 79 } 80 sr.Close(); 81 } 82 } 83 84 } 85 catch (Exception ex) 86 { 87 Logger.Error($"HttpSyncSender,Post,Url:{url},cotentType:{contentType} formData:{JsonConvert.SerializeObject(formData)},header:{headerStr} ex:{ex.Message}"); 88 } 89 finally 90 { 91 webrequest?.Abort(); 92 } 93 return t; 94 } 95 96 /// <summary> 97 /// 同步傳送POST請求 json提交方式 98 /// </summary> 99 /// <typeparam name="T">T型別</typeparam> 100 /// <param name="url">URL</param> 101 /// <param name="jsonModel">POST資料</param> 102 /// <param name="type">返回值型別:JSON、XML</param> 103 /// <param name="timeout">超時時間(單位:毫秒)</param> 104 /// <param name="headers">請求頭</param> 105 /// <param name="referer">來源</param> 106 /// <param name="proxyUrl">代理地址</param> 107 /// <returns>T型別例項</returns> 108 public static T HttpPost<T>(string url, object jsonModel, EnumRequestType type, int timeout, NameValueCollection headers, string referer = "", string proxyUrl = null) where T : new() 109 { 110 T t = default(T); 111 var headerStr = headers == null ? string.Empty : JsonConvert.SerializeObject(headers); 112 if (jsonModel == null) 113 { 114 return t; 115 } 116 HttpWebRequest webrequest = null; 117 try 118 { 119 webrequest = (HttpWebRequest)WebRequest.Create(url); 120 webrequest.Method = "POST"; 121 webrequest.UserAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.2; zh-CN; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3 GTB5"; 122 webrequest.AllowAutoRedirect = true; 123 webrequest.Timeout = timeout; 124 SetRequest(webrequest, true, proxyUrl); 125 126 if (headers != null) 127 { 128 foreach (var item in headers.Keys) 129 { 130 webrequest.Headers.Add(item.ToString(), Convert.ToString(headers[item.ToString()])); 131 } 132 } 133 byte[] byteArray = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(jsonModel)); 134 webrequest.ContentType = "application/json"; 135 webrequest.ContentLength = byteArray.Length; 136 if (!string.IsNullOrWhiteSpace(referer)) 137 { 138 webrequest.Referer = referer; 139 } 140 using (Stream dataStream = webrequest.GetRequestStream()) 141 { 142 dataStream.Write(byteArray, 0, byteArray.Length); 143 } 144 using (var webResponse = (HttpWebResponse)webrequest.GetResponse()) 145 { 146 using (var resStream = UnzipStream(webResponse)) 147 { 148 var sr = new StreamReader(resStream, System.Text.Encoding.UTF8); 149 var result = sr.ReadToEnd(); 150 if (webResponse.StatusCode == HttpStatusCode.OK && !string.IsNullOrEmpty(result)) 151 { 152 t = CreateInstance<T>(result, type); 153 } 154 else 155 { 156 Logger.Error($"HttpSyncSender, Post,返回異常:{webResponse.StatusCode} result:{result} ,Url:{url},cotentType:application/json jsonModel:{JsonConvert.SerializeObject(jsonModel)},header:{headerStr}"); 157 } 158 sr.Close(); 159 } 160 } 161 162 } 163 catch (Exception ex) 164 { 165 Logger.Error($"HttpSyncSender, Post,Url:{url},cotentType:application/json jsonModel:{JsonConvert.SerializeObject(jsonModel)},header:{headerStr}", ex); 166 } 167 finally 168 { 169 webrequest?.Abort(); 170 } 171 return t; 172 } 173 174 /// <summary> 175 /// 同步傳送post請求 檔案上傳 multipart 176 /// </summary> 177 /// <typeparam name="T"></typeparam> 178 /// <param name="url"></param> 179 /// <param name="files"></param> 180 /// <param name="type"></param> 181 /// <param name="timeout"></param> 182 /// <param name="formFields"></param> 183 /// <param name="referer"></param> 184 /// <param name="proxyUrl"></param> 185 /// <remarks>https://docs.microsoft.com/en-us/aspnet/web-api/overview/advanced/sending-html-form-data-part-2</remarks> 186 /// <returns></returns> 187 public static T HttpPost<T>(string url, string[] files, EnumRequestType type, int timeout, NameValueCollection formFields = null, string referer = "", string proxyUrl = null) where T : new() 188 { 189 T t = default(T); 190 HttpWebRequest webrequest = null; 191 if (files == null || files.Length <= 0) 192 { 193 Logger.Error($"HttpPost,multipart Post,Url:{url},files 地址為空"); 194 } 195 var filesStr = JsonConvert.SerializeObject(files); 196 try 197 { 198 var boundary = $"----------------------------{DateTime.Now.Ticks:x}"; 199 webrequest = (HttpWebRequest)WebRequest.Create(url); 200 webrequest.ContentType = "multipart/form-data; boundary=" + boundary; 201 webrequest.Timeout = timeout; 202 webrequest.Method = "POST"; 203 204 var memStream = new MemoryStream(); 205 var boundarybytes = Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n"); 206 var endBoundaryBytes = Encoding.ASCII.GetBytes("\r\n--" + boundary + "--"); 207 208 if (formFields != null) 209 { 210 var formdataTemplate = "\r\n--" + boundary + "\r\nContent-Disposition: form-data; name=\"{0}\";\r\n\r\n{1}"; 211 foreach (string key in formFields.Keys) 212 { 213 var formitem = string.Format(formdataTemplate, key, formFields[key]); 214 byte[] formitembytes = Encoding.UTF8.GetBytes(formitem); 215 memStream.Write(formitembytes, 0, formitembytes.Length); 216 } 217 } 218 219 var headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: application/octet-stream\r\n\r\n"; 220 221 foreach (var file in files) 222 { 223 memStream.Write(boundarybytes, 0, boundarybytes.Length); 224 var header = string.Format(headerTemplate, "uplTheFile", t); 225 var headerbytes = Encoding.UTF8.GetBytes(header); 226 227 memStream.Write(headerbytes, 0, headerbytes.Length); 228 229 using (var fileStream = new FileStream(file, FileMode.Open, FileAccess.Read)) 230 { 231 var buffer = new byte[1024]; 232 int bytesRead; 233 while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0) 234 { 235 memStream.Write(buffer, 0, bytesRead); 236 } 237 } 238 } 239 240 memStream.Write(endBoundaryBytes, 0, endBoundaryBytes.Length); 241 webrequest.ContentLength = memStream.Length; 242 243 using (var requestStream = webrequest.GetRequestStream()) 244 { 245 memStream.Position = 0; 246 byte[] tempBuffer = new byte[memStream.Length]; 247 memStream.Read(tempBuffer, 0, tempBuffer.Length); 248 memStream.Close(); 249 requestStream.Write(tempBuffer, 0, tempBuffer.Length); 250 } 251 using (var webResponse = (HttpWebResponse)webrequest.GetResponse()) 252 { 253 using (var resStream = UnzipStream(webResponse)) 254 { 255 var sr = new StreamReader(resStream, System.Text.Encoding.UTF8); 256 var result = sr.ReadToEnd(); 257 if (webResponse.StatusCode == HttpStatusCode.OK && !string.IsNullOrEmpty(result)) 258 { 259 t = CreateInstance<T>(result, type); 260 } 261 else 262 { 263 Logger.Error($"HttpSyncSender,multipart Post,返回異常:{webResponse.StatusCode} result:{result} ,Url:{url},Url:{url},header:{filesStr}"); 264 } 265 sr.Close(); 266 } 267 } 268 } 269 catch (Exception ex) 270 { 271 Logger.Error($"HttpSyncSender,multipart Post,Url:{url},header:{filesStr}", ex); 272 } 273 finally 274 { 275 webrequest?.Abort(); 276 } 277 return t; 278 279 } 280 281 /// <summary> 282 /// 同步傳送GET請求 283 /// </summary> 284 /// <typeparam name="T">T型別</typeparam> 285 /// <param name="url">URL</param> 286 /// <param name="type">請求型別</param> 287 /// <param name="parameters">引數</param> 288 /// <param name="timeout">超時時間</param> 289 /// <param name="headers">請求頭</param> 290 /// <param name="callback"></param> 291 /// <param name="proxyUrl">代理地址</param> 292 /// <returns>T型別例項</returns> 293 public static T HttpGet<T>(string url, EnumRequestType type, NameValueCollection parameters, int timeout, NameValueCollection headers, string callback = "", string proxyUrl = null) where T : new() 294 { 295 T t = default(T); 296 HttpWebRequest webrequest = null; 297 var headerStr = headers == null ? string.Empty : JsonConvert.SerializeObject(headers); 298 var parametersStr = parameters == null ? string.Empty : JsonConvert.SerializeObject(parameters); 299 try 300 { 301 webrequest = (HttpWebRequest)WebRequest.Create(CreateUrl(url, parameters)); 302 webrequest.Method = "GET"; 303 webrequest.UserAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.2; zh-CN; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3 GTB5"; 304 webrequest.AllowAutoRedirect = true; 305 webrequest.Timeout = timeout; 306 SetRequest(webrequest, false, proxyUrl); 307 308 if (headers != null) 309 { 310 foreach (var item in headers.Keys) 311 { 312 webrequest.Headers.Add(item.ToString(), Convert.ToString(headers[item.ToString()])); 313 } 314 } 315 using (var webResponse = (HttpWebResponse)webrequest.GetResponse()) 316 { 317 using (Stream resStream = UnzipStream(webResponse)) 318 { 319 string result; 320 using (var sr = new StreamReader(resStream, Encoding.UTF8)) 321 { 322 result = sr.ReadToEnd(); 323 } 324 if (webResponse.StatusCode == HttpStatusCode.OK && !string.IsNullOrEmpty(result)) 325 { 326 if (!string.IsNullOrEmpty(callback)) 327 { 328 result = result.TrimStart((callback + "(").ToCharArray()).TrimEnd(')'); 329 } 330 t = CreateInstance<T>(result, type); 331 } 332 else 333 { 334 335 Logger.Error($"HttpSyncSender, Get,返回異常:{webResponse.StatusCode} result:{result} Url:{url},parameters:{parametersStr},header:{headerStr}"); 336 } 337 } 338 } 339 340 } 341 catch (JsonSerializationException je) 342 { 343 Logger.Error($"HttpSyncSender,Get JsonSerializationException,Url:{url},parameters:{parametersStr},header:{headerStr},je:{je.Message}"); 344 throw; 345 } 346 catch (Exception ex) 347 { 348 Logger.Error($"HttpSyncSender, Get,Url:{url},parameters:{parametersStr},header:{headerStr} ex:{ex.Message}"); 349 throw; 350 } 351 finally 352 { 353 webrequest?.Abort(); 354 } 355 return t; 356 } 357 358 private static void SetRequest(HttpWebRequest httpWebRequest, bool post, string proxyUrl = null) 359 { 360 httpWebRequest.MaximumAutomaticRedirections = 3; 361 httpWebRequest.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip,deflate"); 362 httpWebRequest.KeepAlive = true; 363 httpWebRequest.AllowWriteStreamBuffering = false; 364 if (!string.IsNullOrWhiteSpace(proxyUrl)) 365 { 366 httpWebRequest.Proxy = new WebProxy(proxyUrl); 367 } 368 if (post) 369 { 370 //post 較大資料 先進行一次握手,避免資源浪費 371 httpWebRequest.ServicePoint.Expect100Continue = false; 372 } 373 } 374 375 private static Stream UnzipStream(HttpWebResponse httpResponse) 376 { 377 var resStream = httpResponse.GetResponseStream(); 378 if (httpResponse.ContentEncoding.ToLower().Contains("gzip")) 379 { 380 return new GZipStream(resStream, CompressionMode.Decompress); 381 } 382 if (httpResponse.ContentEncoding.ToLower().Contains("deflate")) 383 { 384 return new DeflateStream(resStream, CompressionMode.Decompress); 385 } 386 return resStream; 387 } 388 389 private static T CreateInstance<T>(string text, EnumRequestType type) where T : new() 390 { 391 T t = default(T); 392 if (!string.IsNullOrEmpty(text)) 393 { 394 if (type == EnumRequestType.Json) 395 { 396 t = JsonConvert.DeserializeObject<T>(text); 397 } 398 else 399 { 400 using (Stream stream = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(text))) 401 { 402 XElement element = XElement.Load(stream); 403 if (element != null) 404 { 405 t = new T(); 406 foreach (var item in t.GetType().GetProperties()) 407 { 408 var ele = element.Descendants().SingleOrDefault(c => c.Name.LocalName.ToLower() == item.Name.ToLower()); 409 if (ele != null && !string.IsNullOrEmpty(ele.Value)) 410 { 411 item.SetValue(t, Convert.ChangeType(ele.Value, item.PropertyType), null); 412 } 413 } 414 } 415 } 416 } 417 } 418 return t; 419 } 420 421 private static string CreateUrl(string url, NameValueCollection parameters) 422 { 423 string result = string.Empty; 424 if (!string.IsNullOrEmpty(url)) 425 { 426 result = url; 427 if (parameters != null && parameters.Count > 0) 428 { 429 430 foreach (string key in parameters.Keys) 431 { 432 if (result.IndexOf("?") > -1) 433 { 434 result += "&" + key + "=" + parameters[key]; 435 } 436 else 437 { 438 result += "?" + key + "=" + parameters[key]; 439 } 440 } 441 } 442 } 443 return result; 444 } 445 446 private static string CreateForm(NameValueCollection parameters) 447 { 448 string _form = string.Empty; 449 if (parameters != null && parameters.Count > 0) 450 { 451 foreach (string key in parameters.Keys) 452 { 453 _form += key + "=" + parameters[key] + "&"; 454 } 455 _form = _form.TrimEnd('&'); 456 } 457 return _form; 458 } 459 460 #endregion 461 }View Code