using System; using System.Collections.Generic; using System.Net.Http; using System.Text; using System.Threading; using System.Threading.Tasks; using Newtonsoft.Json; public class HttpClientHelper { // 单例实例 private static readonly Lazy _instance = new Lazy(() => new HttpClientHelper()); // 全局访问属性 public static HttpClientHelper Instance => _instance.Value; // 内部使用的 HttpClient private readonly HttpClient _httpClient; // 私有构造函数,防止外部实例化 private HttpClientHelper() { _httpClient = new HttpClient(); } // 定义内容类型枚举 public enum ContentType { Json, FormData, Text, Xml, Plain, x_www_form } public void SetBaseAddress(string baseAddress) { _httpClient.BaseAddress = new Uri(baseAddress); } // 发送请求的方法(保持原有逻辑不变) public async Task> SendRequestAsync( HttpMethod method, string requestUri, object body = null, Dictionary headers = null, ContentType contentType = ContentType.Json) { var request = new HttpRequestMessage { Method = method, RequestUri = new Uri(_httpClient.BaseAddress, requestUri) }; if (headers != null) { foreach (var header in headers) { request.Headers.Add(header.Key, header.Value); } } if (body != null) { switch (contentType) { case ContentType.Json: request.Content = new StringContent( body.ToString(), Encoding.UTF8, "application/json"); break; case ContentType.FormData: if (body is Dictionary formData) { var multipartContent = new MultipartFormDataContent(); foreach (var pair in formData) { multipartContent.Add(new StringContent(pair.Value, Encoding.UTF8), $"\"{pair.Key}\""); // 注意 Key 要加引号 } request.Content = multipartContent; } else { return ApiResponse.Failure("FormData body must be Dictionary", 400); } break; case ContentType.Text: request.Content = new StringContent( body.ToString(), Encoding.UTF8, "text/plain"); break; case ContentType.Xml: request.Content = new StringContent( body.ToString(), Encoding.UTF8, "application/xml"); break; case ContentType.Plain: request.Content = new StringContent( body.ToString(), Encoding.UTF8, "text/plain"); break; case ContentType.x_www_form: if (body is Dictionary xformData) { var formContent = new FormUrlEncodedContent(xformData); request.Content = formContent; } else { return ApiResponse.Failure("FormData body must be Dictionary", 400); } break; default: return ApiResponse.Failure("Unsupported content type", 400); } } HttpResponseMessage response; try { response = await _httpClient.SendAsync(request); } catch (Exception ex) { return ApiResponse.Failure($"Network error: {ex.Message}", 503); } var responseBody = await response.Content.ReadAsStringAsync(); if (response.IsSuccessStatusCode) { return ApiResponse.Success(responseBody, (int)response.StatusCode); } else { return ApiResponse.Failure(responseBody, (int)response.StatusCode); } } public ApiResponse SendRequest( HttpMethod method, string requestUri, object body = null, Dictionary headers = null, ContentType contentType = ContentType.Json) { var request = new HttpRequestMessage { Method = method, RequestUri = new Uri(_httpClient.BaseAddress, requestUri) }; if (headers != null) { foreach (var header in headers) { request.Headers.Add(header.Key, header.Value); } } if (body != null) { switch (contentType) { case ContentType.Json: request.Content = new StringContent( body.ToString(), Encoding.UTF8, "application/json"); break; case ContentType.FormData: if (body is Dictionary formData) { var multipartContent = new MultipartFormDataContent(); foreach (var pair in formData) { multipartContent.Add( new StringContent(pair.Value, Encoding.UTF8), $"\"{pair.Key}\""); // 注意 key 加引号 } request.Content = multipartContent; } else { return ApiResponse.Failure("FormData body must be Dictionary", 400); } break; case ContentType.x_www_form: if (body is Dictionary xformData) { request.Content = new FormUrlEncodedContent(xformData); } else { return ApiResponse.Failure("FormData body must be Dictionary", 400); } break; case ContentType.Text: case ContentType.Plain: request.Content = new StringContent( body.ToString(), Encoding.UTF8, "text/plain"); break; case ContentType.Xml: request.Content = new StringContent( body.ToString(), Encoding.UTF8, "application/xml"); break; default: return ApiResponse.Failure("Unsupported content type", 400); } } HttpResponseMessage response; try { // ✅ 使用 SendAsync().Result 模拟同步发送 response = _httpClient.SendAsync(request, HttpCompletionOption.ResponseContentRead).Result; } catch (Exception ex) { return ApiResponse.Failure($"Network error: {ex.Message}", 503); } var responseBody = response.Content.ReadAsStringAsync().Result; if (response.IsSuccessStatusCode) { return ApiResponse.Success(responseBody, (int)response.StatusCode); } else { return ApiResponse.Failure(responseBody, (int)response.StatusCode); } } public class ApiResponse { public bool IsSuccess { get; set; } public int StatusCode { get; set; } public string ErrorMessage { get; set; } public T Result { get; set; } public static ApiResponse Success(T result, int statusCode) { return new ApiResponse { IsSuccess = true, StatusCode = statusCode, Result = result }; } public static ApiResponse Failure(string message, int statusCode) { return new ApiResponse { IsSuccess = false, StatusCode = statusCode, ErrorMessage = message }; } } }