C#通过API接口返回流式响应内容---SSE方式

1、背景

今年春节大火的DeepSeek,其中大家比较感兴趣的就是,DeepSeek返回的是一句一句的蹦出来的。这个就是流式响应。C#也可以实现,本篇就是展示流式响应的一个Demo。

2、实现效果

实现的效果如下:

3、具体实现

3.1 API端代码

创建一个asp.net core api项目,在controller中定义流式方式,代码如下:

csharp 复制代码
using Microsoft.AspNetCore.Mvc;

namespace SSEWebApplication.Controllers
{
    [Route("api/[controller]/[action]")]
    [ApiController]
    public class StreamController : ControllerBase
    {
        [HttpGet]
        public async Task GetStreamSse()
        {
            Response.ContentType = "text/event-stream";
            Response.Headers["Cache-Control"] = "no-cache";
            Response.Headers["Connection"] = "keep-alive";
            Response.Headers["Access-Control-Allow-Origin"] = "*"; //可以实现跨域访问

            //假设流式的数据返回
            var messages = new string[] {"你好!","我是","北京清华长庚医院","信息管理部","郑林"};

            //模拟DeepSeek的流式返回
            for (int i = 0; i < messages.Length; i++)
            {
                if(i== messages.Length-1)
                {
                    await Response.WriteAsync($"data:{messages[i]}\n\n");
                    await Response.Body.FlushAsync();
                }
                else
                {
                    await Response.WriteAsync($"data:{messages[i]}\n\n");
                    await Response.Body.FlushAsync();
                    await Task.Delay(1000);
                }
            }
        }
    }
}

3.2 前端代码

前端代码如下:

html 复制代码
<!DOCTYPE html>
<html>

<head>
<title>流式展示</title>
</head>

<body>
    <div id="messages"></div>

<script>
    // 创建SSE连接
    const eventSource =new EventSource('http://localhost:5105/api/Stream/GetStreamSse');
    
    // 监听消息事件
    eventSource.onmessage=function(event) {
        const messageContainer =document.getElementById('messages');
        const newMessage =document.createElement('p');
        newMessage.textContent= event.data;
        messageContainer.appendChild(newMessage);
        
        // 滚动到最新消息
        messageContainer.scrollTop= messageContainer.scrollHeight;
    };
    
    // 监听打开连接事件
    eventSource.onopen=function() {
        console.log("连接已打开");
    };
    
    // 监听错误事件
    eventSource.onerror=function(error) {
        console.error("发生错误", error);
        eventSource.close();// 关闭连接
    };
</script>
</body>
</html>

4、原理

在代码中我们使用了EventSource,这个称之为:服务器发送事件。有点类似socket,只不过这个是单向的,只能服务器发给客户端。

4.1 API的实现

1、API部分很简单,本质上就是一个文本流,类似我们下载文件一样,只不过,下载文件的是Stream流(二进制数据流),而EventSource传递的是string字符串。

2、API端发送有点类似海浪,一波一波的。如何判断发送给前端的这波数据结束了呢,就是\n\n

3、EventSource发送的数据的时候,是有格式要求的:

csharp 复制代码
[发送类型]: 待发送的字符串

发送类型有:event、data、id、retry。

他们怎么用呢?有时候,我们需要把消息发给张三、李四,或同一个界面中的不同部分(股票的最新数据,以及当前企业的财务的消息数据),需要展示/更新界面的不同地方。服务器端就会这么写

csharp 复制代码
if(sendtype=="company")
{
	await Response.WriteAsync($"event:company\n");
	await Response.WriteAsync($"data:发布了第三季度财务报表");	
	await Response.WriteAsync($"\n\n");	
	await Response.Body.FlushAsync();
}else
{
	await Response.WriteAsync($"event:stock\n");
	await Response.WriteAsync($"data:123");	
	await Response.WriteAsync($"\n\n");	
	await Response.Body.FlushAsync();
}

然后前端就可以这么写

typescript 复制代码
evtSource.addEventListener("company", (event) => {
  const newElement = document.createElement("li");
  const eventList = document.getElementById("list");
  const time = JSON.parse(event.data).time;
  newElement.textContent = `ping at ${time}`;
  eventList.appendChild(newElement);
});

evtSource.addEventListener("stock", (event) => {
  const newElement = document.createElement("li");
  const eventList = document.getElementById("list");
  const time = JSON.parse(event.data).time;
  newElement.textContent = `ping at ${time}`;
  eventList.appendChild(newElement);
});

5、参考资料

1、服务器发送事件
2、阮一峰---Server-Sent Events 教程

相关推荐
TO_ZRG5 分钟前
xlua 运行原理
unity·c#
xiaoyan201513 分钟前
vue3仿Deepseek/ChatGPT流式聊天AI界面,对接deepseek/OpenAI API
前端·vue.js·deepseek
用户2587141932631 小时前
C#中Enum(枚举)与Int、String类型之间的转换
c#
互联网打工人no11 小时前
使用c#进行串口通信
c#·rs232
Code_流苏1 小时前
DeepSeek进阶应用(二):结合Kimi制作PPT(双AI协作教程)
kimi·deepseek·ppt制作·进阶应用·ai协作
唐叔在学习4 小时前
一张图彻底拆解DeepSeek V3和R1双模型
deepseek
用户2587141932634 小时前
C#中关于接口(Interface)的详解(附带案例)
c#
计算机学姐4 小时前
基于Asp.net的高校迎新管理系统
vue.js·vscode·后端·mysql·sqlserver·c#·asp.net
offduty4 小时前
大模型体验——表格数据处理
deepseek
AIGC大时代5 小时前
DeepSeek在文献检索中两个相关提示词
chatgpt·文献检索·学术写作·deepseek·aiwritepaper