经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » ASP.net » 查看文章
ASP.NET Core Web API 流式返回,逐字显示
来源:cnblogs  作者:傅小灰  时间:2023/4/24 9:09:45  对本文有异议

Websocket、SSE(Server-Sent Events)和长轮询(Long Polling)都是用于网页和服务端通信的技术。

Websocket是一种全双工通信协议,能够实现客户端和服务端之间的实时通信。它基于TCP协议,并且允许服务器主动向客户端推送数据,同时也允许客户端向服务器发送数据。

SSE是一种单向通信协议,允许服务器向客户端推送数据,但不支持客户端向服务器发送数据。SSE建立在HTTP协议上,通过在HTTP响应中使用特殊的Content-Type和事件流(event stream)格式来实现。

长轮询是一种技术,客户端向服务器发送一个请求,并且服务器保持连接打开直到有数据可以返回给客户端。如果在指定的时间内没有数据可用,则服务器会关闭连接,客户端需要重新建立连接并再次发起请求。

New Bing聊天页面是通过WebSocket进行通信。

Open AI的ChatGPT接口则是通过SSE协议由服务端推送数据

事实上,以上几种方式包括长轮询,都可以实现逐字显示的效果。那还有没有其他的办法可以实现这种效果了呢?

流式响应

当客户端返回流的时候,客户端可以实时捕获到返回的信息,并不需要等全部Response结束了再处理。

下面就用ASP.NET Core Web API作为服务端实现流式响应。

返回文本内容

服务端

  1. [HttpPost("text")]
  2. public async Task Post()
  3. {
  4. string filePath = "文档.txt";
  5. Response.ContentType = "application/octet-stream";
  6. var reader = new StreamReader(filePath);
  7. var buffer = new Memory<char>(new char[5]);
  8. int writeLength = 0;
  9. //每次读取5个字符写入到流中
  10. while ((writeLength = await reader.ReadBlockAsync(buffer)) > 0)
  11. {
  12. if (writeLength < buffer.Length)
  13. {
  14. buffer = buffer[..writeLength];
  15. }
  16. await Response.WriteAsync(buffer.ToString());
  17. await Task.Delay(100);
  18. }
  19. }

客户端

  1. C# HttpClient
  1. public async void GetText()
  2. {
  3. var url = "http://localhost:5000/config/text";
  4. var client = new HttpClient();
  5. using HttpRequestMessage httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, url);
  6. var response = await client.SendAsync(httpRequestMessage, HttpCompletionOption.ResponseHeadersRead);
  7. await using var stream = await response.Content.ReadAsStreamAsync();
  8. var bytes = new byte[20];
  9. int writeLength = 0;
  10. while ((writeLength = stream.Read(bytes, 0, bytes.Length)) > 0)
  11. {
  12. Console.Write(Encoding.UTF8.GetString(bytes, 0, writeLength));
  13. }
  14. Console.WriteLine();
  15. Console.WriteLine("END");
  16. }

HttpCompletionOption枚举有两个值,默认情况下使用的是ResponseContentRead

  • ResponseContentRead:等到整个响应完成才完成操作

  • ResponseHeadersRead:一旦获取到响应头即完成操作,不用等到整个内容响应

  1. js XMLHttpRequest
  1. <script>
  2. var div = document.getElementById("content")
  3. var url = "http://localhost:5000/config/text"
  4. var client = new XMLHttpRequest()
  5. client.open("POST", url)
  6. client.onprogress = function (progressEvent) {
  7. div.innerText = progressEvent.target.responseText
  8. }
  9. client.onloadend = function (progressEvent) {
  10. div.append("END")
  11. }
  12. client.send()
  13. </script>

用axios请求就是监听onDownloadProgress 了。

浏览器是通过Response Header中的Content-Type来解析服务端响应体的。如果后端接口没有设置Response.ContentType = "application/octet-stream"onprogress只会在响应全部完成后触发。

返回图片

服务端

  1. [HttpGet("img")]
  2. public async Task Stream()
  3. {
  4. string filePath = "pixelcity.png";
  5. new FileExtensionContentTypeProvider().TryGetContentType(filePath, out string contentType);
  6. Response.ContentType = contentType ?? "application/octet-stream";
  7. var fileStream = System.IO.File.OpenRead(filePath);
  8. var bytes = new byte[1024];
  9. int writeLength = 0;
  10. while ((writeLength = fileStream.Read(bytes, 0, bytes.Length)) > 0)
  11. {
  12. await Response.Body.WriteAsync(bytes, 0, writeLength);
  13. await Task.Delay(100);
  14. }
  15. }

ImageResponse

原文链接:https://www.cnblogs.com/cplemom/p/17269789.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号