using Microsoft.Extensions.Logging; using System.Text; using System.Text.Json; namespace lai_transfer.Tool.HttpTool; public class HttpRequestConfig { public string? BaseUrl { get; set; } public Dictionary Headers { get; set; } = new(); public Dictionary QueryParams { get; set; } = new(); public string? BearerToken { get; set; } public TimeSpan? Timeout { get; set; } public string? MediaType { get; set; } = "application/json"; public CancellationToken CancellationToken { get; set; } = CancellationToken.None; } public class HttpRequestConfig : HttpRequestConfig { public T? Data { get; set; } } public interface IHttpService { Task GetAsync(string url, HttpRequestConfig? config = null); Task GetStringAsync(string url, HttpRequestConfig? config = null); Task PostAsync(string url, object data, HttpRequestConfig? config = null); Task PostAsync(string url, HttpRequestConfig config); Task PutAsync(string url, object data, HttpRequestConfig? config = null); Task DeleteAsync(string url, HttpRequestConfig? config = null); Task GetStreamAsync(string url, HttpRequestConfig? config = null); Task DownloadFileAsync(string url, HttpRequestConfig? config = null); } public class HttpService : IHttpService { private readonly IHttpClientFactory _httpClientFactory; private readonly ILogger _logger; public HttpService(IHttpClientFactory httpClientFactory, ILogger logger) { _httpClientFactory = httpClientFactory; _logger = logger; } /// /// 配置HttpRequestMessage /// private HttpRequestMessage CreateHttpRequest(HttpMethod method, string url, HttpRequestConfig? config) { var requestUrl = BuildUrl(url, config); var request = new HttpRequestMessage(method, requestUrl); // 设置请求头 SetRequestHeaders(request, config); return request; } /// /// 构建完整URL(包含查询参数) /// private string BuildUrl(string url, HttpRequestConfig? config) { if (config?.QueryParams == null || !config.QueryParams.Any()) return url; var uriBuilder = new UriBuilder(url); var query = System.Web.HttpUtility.ParseQueryString(uriBuilder.Query); foreach (var param in config.QueryParams) { query[param.Key] = param.Value; } uriBuilder.Query = query.ToString(); return uriBuilder.ToString(); } /// /// 设置请求头 /// private void SetRequestHeaders(HttpRequestMessage request, HttpRequestConfig? config) { if (config == null) return; // 设置Bearer Token if (!string.IsNullOrEmpty(config.BearerToken)) { request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", config.BearerToken); } // 设置自定义请求头 foreach (var header in config.Headers) { request.Headers.TryAddWithoutValidation(header.Key, header.Value); } // 设置Content-Type if (request.Content != null && !string.IsNullOrEmpty(config.MediaType)) { request.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(config.MediaType); } } /// /// 发送HTTP请求 /// private async Task SendAsync(HttpRequestMessage request, HttpRequestConfig? config, string clientName = "DefaultClient") { using var httpClient = _httpClientFactory.CreateClient(clientName); // 设置超时 if (config?.Timeout.HasValue == true) { httpClient.Timeout = config.Timeout.Value; } return await httpClient.SendAsync(request, config?.CancellationToken ?? CancellationToken.None); } /// /// GET请求 - 返回泛型类型 /// public async Task GetAsync(string url, HttpRequestConfig? config = null) { try { var request = CreateHttpRequest(HttpMethod.Get, url, config); var response = await SendAsync(request, config); response.EnsureSuccessStatusCode(); var content = await response.Content.ReadAsStringAsync(); return JsonSerializer.Deserialize(content, new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); } catch (Exception ex) { _logger.LogError(ex, "GET请求失败: {Url}", url); throw; } } /// /// GET请求 - 返回字符串 /// public async Task GetStringAsync(string url, HttpRequestConfig? config = null) { try { var request = CreateHttpRequest(HttpMethod.Get, url, config); var response = await SendAsync(request, config); response.EnsureSuccessStatusCode(); return await response.Content.ReadAsStringAsync(); } catch (Exception ex) { _logger.LogError(ex, "GET字符串请求失败: {Url}", url); throw; } } /// /// POST请求 /// public async Task PostAsync(string url, object data, HttpRequestConfig? config = null) { try { var request = CreateHttpRequest(HttpMethod.Post, url, config); // 判断data是不是string 不是的话才序列话 string json; if (data is string str) { // 如果 data 已经是字符串,直接使用 json = str; } else { // 如果是对象,序列化为 JSON json = JsonSerializer.Serialize(data); } request.Content = new StringContent(json, Encoding.UTF8, config?.MediaType ?? "application/json"); var response = await SendAsync(request, config); response.EnsureSuccessStatusCode(); var content = await response.Content.ReadAsStringAsync(); return JsonSerializer.Deserialize(content, new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); } catch (Exception ex) { _logger.LogError(ex, "POST请求失败: {Url}", url); throw; } } /// /// POST请求 - 泛型配置版本 /// public async Task PostAsync(string url, HttpRequestConfig config) { return await PostAsync(url, config.Data!, config); } /// /// PUT请求 /// public async Task PutAsync(string url, object data, HttpRequestConfig? config = null) { try { var request = CreateHttpRequest(HttpMethod.Put, url, config); var json = JsonSerializer.Serialize(data); request.Content = new StringContent(json, Encoding.UTF8, config?.MediaType ?? "application/json"); var response = await SendAsync(request, config); response.EnsureSuccessStatusCode(); var content = await response.Content.ReadAsStringAsync(); return JsonSerializer.Deserialize(content, new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); } catch (Exception ex) { _logger.LogError(ex, "PUT请求失败: {Url}", url); throw; } } /// /// DELETE请求 /// public async Task DeleteAsync(string url, HttpRequestConfig? config = null) { try { var request = CreateHttpRequest(HttpMethod.Delete, url, config); var response = await SendAsync(request, config); return response.IsSuccessStatusCode; } catch (Exception ex) { _logger.LogError(ex, "DELETE请求失败: {Url}", url); throw; } } /// /// 下载文件流 /// public async Task GetStreamAsync(string url, HttpRequestConfig? config = null) { try { var request = CreateHttpRequest(HttpMethod.Get, url, config); var response = await SendAsync(request, config); response.EnsureSuccessStatusCode(); var stream = await response.Content.ReadAsStreamAsync(); // 转移所有权,调用方负责释放 response = null; return stream; } catch (Exception ex) { _logger.LogError(ex, "获取流失败: {Url}", url); throw; } } /// /// 下载文件字节数组 /// public async Task DownloadFileAsync(string url, HttpRequestConfig? config = null) { try { using var stream = await GetStreamAsync(url, config); using var memoryStream = new MemoryStream(); await stream.CopyToAsync(memoryStream); return memoryStream.ToArray(); } catch (Exception ex) { _logger.LogError(ex, "下载文件失败: {Url}", url); throw; } } }