经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » C# » 查看文章
【分段传输】c#使用IAsyncEnumerable实现流式分段传输
来源:cnblogs  作者:四处观察  时间:2023/10/23 9:01:54  对本文有异议

引言

    在使用SSE的时候,前端可以实现流式传输,但是有个问题就是这是一个独占的连接,相当于如果你不手动关闭连接,就会一直请求,一直连接调用接口,而且发送的数据格式也是按照定义好的协议来,而使用c#自带的IAsyncEnumerable也可以实现流式传输,不过返回的数据是在之前返回的基础上进行累加,需要自己做处理,我的例子是使用的是ajax来实现,群友有提供了fetch的实现代码,接下来我们看看c#IAsyncEnumerable实现传输的ajax方案和fetch的代码吧。

AJAX

     下面是源码和gif效果展示,可以看到我们返回的是一个IAsyncEnumerable<int>类型的结果,在第二段代码,我们都知道ajax是根据xhrhttprequest封装的,所以自然也可以用一些它的一些事件,所以我们在此处用了onprogress来监听我们请求的进度,在这里我们就可以获取到每一次写了哪些东西,从而实现一个流传输,因为后端写也是一个字节一个字节去写的,前端接收也是如此。

  1. [HttpGet("Postb")]
  2. public async IAsyncEnumerable<int> PostB()
  3. {
  4. await foreach (var item in GetData())
  5. {
  6. yield return item;
  7. }
  8. }
  9. private async IAsyncEnumerable<int> GetData()
  10. {
  11. foreach (int item in Enumerable.Range(0,100))
  12. {
  13. await Task.Delay(100);
  14. yield return item;
  15. }
  16. }

 

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title>AJAX Example</title>
  5. <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
  6. <script>
  7.  
  8. function callAjax() {
  9. $.ajax({
  10. url: 'http://localhost:5203/WeatherForecast/Postb',
  11. method: 'GET',
  12. contentType: 'application/json',
  13. xhrFields: {
  14. onprogress: function (e) {
  15. var msg = e.currentTarget.response;
  16. $("#list").append(`<h5>${msg}</h5>`);
  17. console.log("接收的数据是=>" + msg);
  18. },
  19. onchange: function (a) {
  20. debugger;
  21. }
  22. },
  23. success: function () {
  24. console.log("分块读取完成");
  25. },
  26. error: function (xhr, status, error) {
  27. console.log("请求失败");
  28. console.log("错误信息: " + error);
  29. }
  30. });
  31. }
  32. </script>
  33. </head>
  34. <body>
  35. <button onclick="callAjax()">调用AJAX</button>
  36. </body>
  37. </html>

 SSE

    SSE全称Server Sent Event,从名字我们可以看出,这是一个服务端单向发送到客户端的,与WebSocket不同,但是两者都是长连接,上面的ajax的响应标头是applycation/json,SSE的必须是text/event-stream,并且SSE的发送的参数也都是有固定的格式,每一个发送的消息都是由\n\n分割,每一个message由若干个可选的字段组成,例如下面,field:value是一个message里面的内容,field可选范围是下面那四个,第二代码段是后端的代码,展示了一个完整的message,包括了data,event,retry和id,其中上面,我们设置了响应的Content-type是text/event-stream,设置是不缓存no-cache,下面设置是保持连接,keepalive,因为是长连接嘛,id和data可以随便给,retry是端口连接后的一个重新连接时间,event是一个事件的名称,我们给客户端返回这个格式的内容,客户端就会根据这个内容就返回数据,调用我们的event,从而实现一个流式输出。

  1. [field]: value\n //这是一个Message
  2. //下面是可选的字段
  3. data
  4. event
  5. id
  6. retry
  1. [HttpGet("Posta")]
  2. public IActionResult Posta()
  3. {
  4. if (Response.Headers.ContainsKey("Content-Type"))
  5. {
  6. Response.Headers.Remove("Content-Type");
  7. Response.Headers.Add("Content-Type", "text/event-stream");
  8. }
  9. else
  10. {
  11. Response.Headers.Add("Content-Type", "text/event-stream");
  12. }
  13. Response.Headers.Add("Cache-Control", "no-cache");
  14. Response.Headers.Add("Connection", "keep-alive");
  15. string data =
  16. $"id: {Random.Shared.Next()} \n" +
  17. $"retry: {Random.Shared.Next(0, 100) * 30}\n" +
  18. $"event: message\n" +
  19. $"data: {Random.Shared.Next()}\n\n";return Content(data);
  20. }
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title>SSE Example</title>
  5. <script>
  6. var eventSource = new EventSource("http://localhost:5203/WeatherForecast/Posta");
  7. eventSource.addEventListener("message", function(event) {
  8. var a=document.getElementById("aaa");
  9. a.innerHTML+="<a>"+event.data+"</a><br>"
  10. console.log("Received message: " + event.data);
  11. });
  12. eventSource.addEventListener("error", function(event) {
  13. console.log("Error occurred");
  14. });
  15. </script>
  16. </head>
  17. <body>
  18. <div id='aaa'></div>
  19. </body>
  20. </html>

 总结

    以上便是今天的全部内容,当然,图片的流式传输,返回html然后显示,也可以直接去给响应流写数据,content-type是stream的形式,会一点一点的加载,感兴趣的朋友可以自己手动尝试一下下咯。

原文链接:https://www.cnblogs.com/1996-Chinese-Chen/p/17776939.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号