新增 Mjpegplayer 用来播放 Web 流
This commit is contained in:
120
SHH.MjpegPlayer/Core/Extensions/NetHttpExtension.cs
Normal file
120
SHH.MjpegPlayer/Core/Extensions/NetHttpExtension.cs
Normal file
@@ -0,0 +1,120 @@
|
||||
using Ayay.SerilogLogs;
|
||||
using Newtonsoft.Json;
|
||||
using Serilog;
|
||||
using System.Text;
|
||||
|
||||
namespace SHH.MjpegPlayer;
|
||||
|
||||
/// <summary>
|
||||
/// 扩展 HttpClient 的 PostJson 方法,用于发送 JSON 格式的数据
|
||||
/// </summary>
|
||||
public static class NetHttpExtension
|
||||
{
|
||||
// Optimized: 统一日志对象
|
||||
private static readonly ILogger _sysLog = Log.ForContext("SourceContext", LogModules.Core);
|
||||
|
||||
// Optimized: 使用静态单例 HttpClient 防止套接字耗尽。注意:生产环境建议配合 SocketsHttpHandler
|
||||
private static readonly HttpClient _httpClient = new HttpClient();
|
||||
|
||||
#region 同步方法 (Sync-over-Async, 谨慎使用)
|
||||
|
||||
/// <summary>
|
||||
/// 发送 JSON 格式的 POST 请求 (同步)
|
||||
/// </summary>
|
||||
public static string PostJson(this object jsonData, string url, int timeout = 2000)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Optimized: 显式调用异步版本并等待,注意在某些上下文可能死锁
|
||||
return PostJsonAsync(jsonData, url, timeout).GetAwaiter().GetResult();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_sysLog.Error(ex, "Post 同步请求异常: {Url}", url);
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发送 JSON 格式的 POST 请求并反序列化 (同步)
|
||||
/// </summary>
|
||||
public static T? PostJson<T>(this object jsonData, string url, int timeout = 2000)
|
||||
{
|
||||
try
|
||||
{
|
||||
var msg = PostJson(jsonData, url, timeout);
|
||||
return string.IsNullOrWhiteSpace(msg) ? default : JsonConvert.DeserializeObject<T>(msg);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_sysLog.Error(ex, "Post 同步请求并解析 JSON 异常: {Url}", url);
|
||||
return default;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 异步方法 (推荐使用)
|
||||
|
||||
/// <summary>
|
||||
/// 发送 JSON 格式的 POST 请求 (异步)
|
||||
/// </summary>
|
||||
/// <param name="jsonData">要发送的对象</param>
|
||||
/// <param name="url">目标地址</param>
|
||||
/// <param name="timeout">超时(ms)</param>
|
||||
public static async Task<string> PostJsonAsync(this object jsonData, string url, int timeout = 2000)
|
||||
{
|
||||
string jsonString = string.Empty;
|
||||
try
|
||||
{
|
||||
// Optimized: 序列化处理
|
||||
jsonString = jsonData is string s ? s : JsonConvert.SerializeObject(jsonData);
|
||||
using var content = new StringContent(jsonString, Encoding.UTF8, "application/json");
|
||||
|
||||
// Optimized: 设置请求级别的超时处理(HttpClient.Timeout 是全局的,此处利用 CancellationTokenSource)
|
||||
using var cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(timeout));
|
||||
|
||||
var response = await _httpClient.PostAsync(url, content, cts.Token);
|
||||
|
||||
if (response.IsSuccessStatusCode)
|
||||
{
|
||||
return await response.Content.ReadAsStringAsync();
|
||||
}
|
||||
|
||||
_sysLog.Warning("Post 请求状态异常: {Url}, StatusCode: {Code}", url, response.StatusCode);
|
||||
return string.Empty;
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
_sysLog.Warning("Post 请求超时: {Url}, Timeout: {Timeout}ms", url, timeout);
|
||||
return string.Empty;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Modified: 使用结构化日志记录错误
|
||||
_sysLog.Error(ex, "Post 异步请求发生故障: {Url}", url);
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发送 JSON 格式的 POST 请求并反序列化 (异步)
|
||||
/// </summary>
|
||||
public static async Task<T?> PostJsonAsync<T>(this object jsonData, string url, int timeout = 2000)
|
||||
{
|
||||
try
|
||||
{
|
||||
var result = await PostJsonAsync(jsonData, url, timeout);
|
||||
if (string.IsNullOrWhiteSpace(result)) return default;
|
||||
|
||||
return JsonConvert.DeserializeObject<T>(result);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_sysLog.Error(ex, "Post 异步请求解析 JSON 失败: {Url}", url);
|
||||
return default;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
Reference in New Issue
Block a user