diff --git a/WeiCloud.Fusion/VideoService/Video.API/Program.cs b/WeiCloud.Fusion/VideoService/Video.API/Program.cs index d28df52..2cb6d35 100644 --- a/WeiCloud.Fusion/VideoService/Video.API/Program.cs +++ b/WeiCloud.Fusion/VideoService/Video.API/Program.cs @@ -1,6 +1,5 @@ using Autofac; using Autofac.Extensions.DependencyInjection; -using Common.Shared.Application.DaHua; using Common.Shared.DomainService; using Microsoft.OpenApi.Models; using NLog; diff --git a/WeiCloud.Fusion/VideoService/Video.API/appsettings.json b/WeiCloud.Fusion/VideoService/Video.API/appsettings.json index 8cdbf31..45fd41c 100644 --- a/WeiCloud.Fusion/VideoService/Video.API/appsettings.json +++ b/WeiCloud.Fusion/VideoService/Video.API/appsettings.json @@ -28,18 +28,18 @@ "Username": "system", "Password": "Admin123", "Real": { - "DefaultRoot": "192.168.21.18:9100", - "DefaultReplace": "demo.weienergy.cn:15210", + "DefaultRoot": "192.168.21.18:9102", + "DefaultReplace": "demo.weienergy.cn:15235", "Overrides": { - "192.168.21.18:9100": "demo.weienergy.cn:15210", - "10.20.30.40:9100": "demo.weienergy.cn:15210" + "192.168.21.18:9100": "demo.weienergy.cn:15235", + "10.20.30.40:9100": "demo.weienergy.cn:15235" } }, "Time": { - "DefaultRoot": "192.168.21.18:9320", - "DefaultReplace": "demo.weienergy.cn:15211", + "DefaultRoot": "192.168.21.18:9322", + "DefaultReplace": "demo.weienergy.cn:15232", "Overrides": { - "192.168.21.18:9320": "demo.weienergy.cn:15211" + "192.168.21.18:9320": "demo.weienergy.cn:15232" } } } diff --git a/WeiCloud.Fusion/VideoService/Video.DomainService/Dahvision/DahuaGeneralCtlService.cs b/WeiCloud.Fusion/VideoService/Video.DomainService/Dahvision/DahuaGeneralCtlService.cs index 4d5c52c..7d6c140 100644 --- a/WeiCloud.Fusion/VideoService/Video.DomainService/Dahvision/DahuaGeneralCtlService.cs +++ b/WeiCloud.Fusion/VideoService/Video.DomainService/Dahvision/DahuaGeneralCtlService.cs @@ -72,8 +72,10 @@ namespace Video.DomainService req.Headers.TryAddWithoutValidation("Authorization", token); using var resp = await _http.SendAsync(req); - var body = await resp.Content.ReadAsStringAsync(); - + resp.EnsureSuccessStatusCode(); + await using var stream = await resp.Content.ReadAsStreamAsync(); + using var reader = new StreamReader(stream); + var body = await reader.ReadToEndAsync(); if (!resp.IsSuccessStatusCode) { _logger.LogWarning("录像请求 HTTP 失败: {Status}, Body: {Body}", (int)resp.StatusCode, body); @@ -134,7 +136,11 @@ namespace Video.DomainService try { using var resp = await _http.SendAsync(req); // 关键:用 SendAsync 发送 req,才能带上头 - var body = await resp.Content.ReadAsStringAsync(); + resp.EnsureSuccessStatusCode(); + + await using var stream = await resp.Content.ReadAsStreamAsync(); + using var reader = new StreamReader(stream); + var body = await reader.ReadToEndAsync(); if (!resp.IsSuccessStatusCode) { @@ -192,7 +198,11 @@ namespace Video.DomainService try { using var resp = await _http.SendAsync(req); // 关键:用 SendAsync 发送 req - var body = await resp.Content.ReadAsStringAsync(); + resp.EnsureSuccessStatusCode(); + + await using var stream = await resp.Content.ReadAsStreamAsync(); + using var reader = new StreamReader(stream); + var body = await reader.ReadToEndAsync(); if (!resp.IsSuccessStatusCode) { @@ -257,8 +267,11 @@ namespace Video.DomainService req.Headers.TryAddWithoutValidation("Authorization", token); using var resp = await _http.SendAsync(req); - var body = await resp.Content.ReadAsStringAsync(); + resp.EnsureSuccessStatusCode(); + await using var stream = await resp.Content.ReadAsStreamAsync(); + using var reader = new StreamReader(stream); + var body = await reader.ReadToEndAsync(); if (!resp.IsSuccessStatusCode) { _logger.LogWarning("实时流请求 HTTP 失败: {Status}, Body: {Body}", (int)resp.StatusCode, body); @@ -298,41 +311,57 @@ namespace Video.DomainService { var url = $"https://{_configuration["DahuaAuth:Host"]}/evo-apigw/evo-oauth/1.0.0/oauth/logout"; + using var req = new HttpRequestMessage(HttpMethod.Get, url); + req.Headers.TryAddWithoutValidation("Authorization", authorization); + if (!string.IsNullOrWhiteSpace(openId)) + req.Headers.Add("openId", openId); + if (userClient != null) + req.Headers.Add("User-Client", userClient.ToString()); + try { - using var req = new HttpRequestMessage(HttpMethod.Get, url); - req.Headers.TryAddWithoutValidation("Authorization", authorization); - if (!string.IsNullOrWhiteSpace(openId)) + using var resp = await _http.SendAsync(req, HttpCompletionOption.ResponseHeadersRead); + var body = await resp.Content.ReadAsStringAsync(); + + // 不抛异常,让业务逻辑决定是否失败 + if (!resp.IsSuccessStatusCode) { - req.Headers.Add("openId", openId); + _logger.LogWarning("注销登录 HTTP失败: {Status}, Body: {Body}", (int)resp.StatusCode, body); + return new DaHApiResult + { + Success = false, + Code = ((int)resp.StatusCode).ToString(), + Msg = $"HTTP错误 {(int)resp.StatusCode}", + }; } - if (userClient != null) + + // 尝试反序列化 + var result = JsonSerializer.Deserialize>(body); + if (result == null) { - req.Headers.Add("User-Client", userClient.ToString()); + _logger.LogWarning("注销登录反序列化失败: {Body}", body); + return new DaHApiResult { Success = false, Code = "1011", Msg = "注销登录返回无效" }; } - using var resp = await _http.SendAsync(req); - resp.EnsureSuccessStatusCode(); - - var result = await resp.Content.ReadFromJsonAsync>(); - - if (result != null && (result.Success || result.Code != "0")) + // 只有 Success==false 或 Code != "0" 才视为失败 + if (!result.Success || result.Code != "0") { + _logger.LogWarning("注销登录失败: {Body}", body); result.Success = false; - result.Code = "1011"; - result.Msg = "注销登录失败"; - _logger.LogWarning("注销登录失败,返回结果:{Result}", result); + result.Code = result.Code ?? "1011"; + result.Msg ??= "注销登录失败"; } + return result; } catch (Exception ex) { - _logger.LogError(ex, "大华注销登录出错"); + _logger.LogError(ex, "大华注销登录异常"); return new DaHApiResult { Success = false, Code = "1011", - Msg = "注销登录失败" + Msg = $"注销登录异常:{ex.Message}" }; } } @@ -387,7 +416,11 @@ namespace Video.DomainService reqs.Headers.TryAddWithoutValidation("Authorization", token); using var resp = await _http.SendAsync(reqs); - var bodys = await resp.Content.ReadAsStringAsync(); + resp.EnsureSuccessStatusCode(); + + await using var stream = await resp.Content.ReadAsStreamAsync(); + using var reader = new StreamReader(stream); + var bodys = await reader.ReadToEndAsync(); var resultRecord = JsonSerializer.Deserialize>(bodys); if (resultRecord == null || !resultRecord.Success) { @@ -482,8 +515,11 @@ namespace Video.DomainService try { using var resp = await _http.SendAsync(req); // 关键:用 SendAsync 发 req - var body = await resp.Content.ReadAsStringAsync(); + resp.EnsureSuccessStatusCode(); + await using var stream = await resp.Content.ReadAsStreamAsync(); + using var reader = new StreamReader(stream); + var body = await reader.ReadToEndAsync(); if (!resp.IsSuccessStatusCode) { _logger.LogWarning("实时流请求 HTTP 失败: {Status}, Body: {Body}", (int)resp.StatusCode, body); @@ -567,8 +603,11 @@ namespace Video.DomainService try { using var resp = await _http.SendAsync(req); - var body = await resp.Content.ReadAsStringAsync(); + resp.EnsureSuccessStatusCode(); + await using var stream = await resp.Content.ReadAsStreamAsync(); + using var reader = new StreamReader(stream); + var body = await reader.ReadToEndAsync(); if (!resp.IsSuccessStatusCode) { _logger.LogWarning("抓拍 失败: {Status}, Body: {Body}", (int)resp.StatusCode, body); @@ -630,8 +669,11 @@ namespace Video.DomainService try { using var resp = await _http.SendAsync(req); - var body = await resp.Content.ReadAsStringAsync(); + resp.EnsureSuccessStatusCode(); + await using var stream = await resp.Content.ReadAsStreamAsync(); + using var reader = new StreamReader(stream); + var body = await reader.ReadToEndAsync(); if (!resp.IsSuccessStatusCode) { _logger.LogWarning("控制云台镜头失败: {Status}, Body: {Body}", (int)resp.StatusCode, body); @@ -690,8 +732,11 @@ namespace Video.DomainService try { using var resp = await _http.SendAsync(req); - var body = await resp.Content.ReadAsStringAsync(); + resp.EnsureSuccessStatusCode(); + await using var stream = await resp.Content.ReadAsStreamAsync(); + using var reader = new StreamReader(stream); + var body = await reader.ReadToEndAsync(); if (!resp.IsSuccessStatusCode) { _logger.LogWarning("云台方向控制失败: {Status}, Body: {Body}", (int)resp.StatusCode, body); diff --git a/WeiCloud.Fusion/VideoService/Video.DomainService/Dahvision/UrlHostReplacer.cs b/WeiCloud.Fusion/VideoService/Video.DomainService/Dahvision/UrlHostReplacer.cs index 1d4e020..2ec0d92 100644 --- a/WeiCloud.Fusion/VideoService/Video.DomainService/Dahvision/UrlHostReplacer.cs +++ b/WeiCloud.Fusion/VideoService/Video.DomainService/Dahvision/UrlHostReplacer.cs @@ -7,20 +7,28 @@ namespace Video.DomainService.Dahvision public static string ReplaceHost(string url, string? ipAddress, IConfiguration config, string sectionName) { var section = config.GetSection($"DahuaAuth:{sectionName}"); - var defaultRoot = section["DefaultRoot"]!; var defaultReplace = section["DefaultReplace"]!; + var overrides = section.GetSection("Overrides").Get>() ?? new(); - // 1) 确定 fromHost - var fromHost = string.IsNullOrWhiteSpace(ipAddress) ? defaultRoot : ipAddress; + // 自动提取 host:port + string hostAndPort; + if (url.Contains("://")) + { + var uri = new Uri(url); + hostAndPort = $"{uri.Host}:{uri.Port}"; + } + else + { + // url 是纯 IP:Port,比如 "192.168.21.18:9100" + hostAndPort = url; + } - // 2) 尝试在 Overrides 找对应的 value - var overrides = section.GetSection("Overrides").Get>() ?? new(); - var toHost = overrides.TryGetValue(fromHost, out var mapped) - ? mapped - : defaultReplace; + // 优先使用 Overrides 中的映射 + if (!overrides.TryGetValue(hostAndPort, out var toHost)) + toHost = defaultReplace; - // 3) 字符串替换 - return url.Replace(fromHost, toHost, StringComparison.OrdinalIgnoreCase); + // 替换 + return url.Replace(hostAndPort, toHost, StringComparison.OrdinalIgnoreCase); } } } \ No newline at end of file