using Microsoft.AspNetCore.Http.Features; using Newtonsoft.Json; using Newtonsoft.Json.Serialization; /// /// SSE 流式数据助手类,提供初始化 SSE、发送数据包和结束流的方法 /// public static class SseAlchemyHelper { private static readonly JsonSerializerSettings _jsonSettings = new() { ContractResolver = new CamelCasePropertyNamesContractResolver(), DateTimeZoneHandling = DateTimeZoneHandling.Local, NullValueHandling = NullValueHandling.Ignore }; /// /// 初始化 SSE /// public static void InitializeSse(this HttpContext context) { var syncIOFeature = context.Features.Get(); if (syncIOFeature != null) syncIOFeature.AllowSynchronousIO = true; var response = context.Response; response.Headers.Append("Content-Type", "text/event-stream"); response.Headers.Append("Cache-Control", "no-cache"); response.Headers.Append("Connection", "keep-alive"); response.Headers.Append("X-Accel-Buffering", "no"); } /// /// 发送流数据包 /// public static async Task SendSseStepAsync( this HttpContext context, int progress, string message, object? data = null) { // 检查客户端是否已断开连接 if (context.RequestAborted.IsCancellationRequested) return; var payload = JsonConvert.SerializeObject(new { progress, message, data }, _jsonSettings); string sseFormattedData = $"data: {payload}\n\n"; byte[] bytes = Encoding.UTF8.GetBytes(sseFormattedData); try { // 写入并立即冲刷到客户端 await context.Response.Body.WriteAsync(bytes, 0, bytes.Length, context.RequestAborted); await context.Response.Body.FlushAsync(context.RequestAborted); } catch (OperationCanceledException) { /* 客户端取消,优雅退出 */ } catch (Exception) { /* 忽略其他写入异常 */ } } /// /// 结束 SSE 流 /// public static async Task FinalizeSseAsync(this HttpContext context) { if (!context.RequestAborted.IsCancellationRequested) { await context.Response.Body.FlushAsync(); } } }