最近用asp.net core webapi实现了一个实时视频流的推送功能,在Asp.net中,这个是通过PushStreamContent来实现的。

基于对asp.net core的知识,随手写了一个(要求控制器继承自Controller基类)

[HttpGet]
public async Task Get()
{
var response = HttpContext.Response;
response.ContentType = "text/html";
response.StatusCode = ;
var stream = HttpContext.Response.Body; while (true)
{
await Task.Delay();
var content = DateTime.Now + @"<br>";
var data = Encoding.Default.GetBytes(content);
await stream.WriteAsync(data, , data.Length);
await stream.FlushAsync();
}
}

使用chrome调试这个接口时,发现它确实行之有效的将当前的时间推送到了浏览器的页面上。

然而,当我进一步的调试它的异常情况时,发现就算将chrome关掉,这个程序却依然在继续运行。从调试器中看到stream的状态为Aborted,已经识别到位终止的流了。

  

并且从VS的调试窗口也能看到异常信息:

  

但下面这两行就是不抛异常:

await stream.WriteAsync(data, , data.Length);
await stream.FlushAsync();

单单从接口的实现角度上来看,这个已经不合理了。这是一个很大的坑,功能看上去还是正确的,没有详细调试还看不出来。一个不留神就踩上了。不知道微软为什么要这么设计。

埋怨归埋怨,问题还是要解决的。我查看了下FileStreamResult的源码,发现它是靠HttpContext.RequestAborted来判断客户端是否终止了的。这是一个CancellationToken类型的对象,当客户端连接断开后,它就处于被取消的状态。

知道原因后,就可以知道如何修改我的程序了。

[HttpGet]
public async Task Get()
{
var cancel = HttpContext.RequestAborted; var response = HttpContext.Response;
response.ContentType = "text/html";
response.StatusCode = ;
var stream = HttpContext.Response.Body; while (true)
{
cancel.ThrowIfCancellationRequested();
await Task.Delay(, cancel);
var content = DateTime.Now + @"<br>";
var data = Encoding.Default.GetBytes(content);
await stream.WriteAsync(data, , data.Length, cancel);
await stream.FlushAsync(cancel);
}
}

再然后就是封装了,我这里将其封装为了一个PushStreamResult,这样就可以在PocoController中使用了。

class MyPushStreamResult :IActionResult
{
Func<Stream, CancellationToken, Task> _pushAction;
string _contentType; public MyPushStreamResult(Func<Stream, CancellationToken, Task> pushAction, string contentType)
{
_pushAction = pushAction;
_contentType = contentType;
} public Task ExecuteResultAsync(ActionContext context)
{
var response = context.HttpContext.Response;
response.ContentType = _contentType;
response.StatusCode = ; return _pushAction(response.Body, context.HttpContext.RequestAborted);
}
}

使用方法如下:

[HttpGet]
public IActionResult Get()
{
return new MyPushStreamResult(pushData, "text/html");
} async Task pushData(Stream stream, CancellationToken cancel)
{
while (true)
{
if (cancel.IsCancellationRequested)
return;
await Task.Delay(, cancel);
var content = DateTime.Now + @"<br>";
var data = Encoding.Default.GetBytes(content);
await stream.WriteAsync(data, , data.Length, cancel);
await stream.FlushAsync(cancel);
}
}

在Asp.net core返回PushStream的更多相关文章

  1. ASP.NET Core 返回 Json DateTime 格式

    ASP.NET Core 返回 Json 格式的时候,如果返回数据中有DateTime类型,如何自定义其格式呢?配置如下: services.AddMvc().AddJsonOptions(opt = ...

  2. ASP.NET Core 返回文件、用户下载文件,从网站下载文件,动态下载文件

    ASP.NET Core 中,可以在静态目录添加文件,直接访问就可以下载.但是这种方法可能不安全,也不够灵活. 我们可以在 Controller 控制器中 添加 一个 Action,通过此Action ...

  3. ASP.Net Core 返回的json数据,自定义日期格式

    //代码位置:Startup.cs public void ConfigureServices(IServiceCollection services) { services.AddMvc() .Ad ...

  4. ASP.NET Core 如何实现404错误跳转到主页

    假如用户在Web浏览器上敲错了URL,访问了ASP.NET Core站点下一个不存在的URL地址,那么默认情况下ASP.NET Core会返回给浏览器著名的404错误,那么有什么办法可以让ASP.NE ...

  5. 剖析ASP.NET Core(Part 4)- 调用MVC中间件(译)

    原文:https://www.stevejgordon.co.uk/invoking-mvc-middleware-asp-net-core-anatomy-part-4 发布于:2017年5月环境: ...

  6. Asp.net Core WebApi 支持json/xml格式的数据返回

    Asp.net core 在做webapi项目的时候,默认是只返回json格式的数据的,如果想要开启xml数据返回,需要在startup里配置如下: public void ConfigureServ ...

  7. Asp.net Core WebApi 返回JSON自动驼峰格式化问题

    从今天开始,正式进入Asp.net Core的开发,估计最近一段时间会经常写博客了,记录学些Asp.net Core中遇到的各种坑. 第一个问题:通过core编写的webapi,默认返回的json会自 ...

  8. ASP.NET Core WebApi 返回统一格式参数(Json 中 Null 替换为空字符串)

    相关博文:ASP.NET Core WebApi 返回统一格式参数 业务场景: 统一返回格式参数中,如果包含 Null 值,调用方会不太好处理,需要替换为空字符串,示例: { "respon ...

  9. ASP.NET Core WebAPI控制器返回类型的最佳选项

    前言 从.NET Core 2.1版开始,到目前为止,控制器操作可以返回三种类型的WebApi响应.这三种类型都有自己的优点和缺点,但都缺乏满足REST和高可测性的选项. ASP.NET Core中可 ...

随机推荐

  1. Linux - awk 文本处理工具五

    awk 线上处理常用模式 awk 处理复杂日志 6.19: DHB_014_号百总机服务业务日报:广州 到达数异常! DHB_023_号百漏话提醒日报:珠海 到达数异常! 6.20: DHB_014_ ...

  2. 【转载】maven pom详解(2)

    setting.xml主要用于配置maven的运行环境等一系列通用的属性,是全局级别的配置文件:而pom.xml主要描述了项目的maven坐标,依赖关系,开发者需要遵循的规则,缺陷管理系统,组织和li ...

  3. usb device address error 110

    ubuntu失灵了,怎么都起不来,报一堆错误usb device descriptor read/64, error 110......重启,换kvm的接口,usb键盘鼠标...终于在试了下面这个方法 ...

  4. HTML播放FLASH(SWF)神器-SWFObject

    环境 必须有 swfobject.js和 expressInstall.swf js:  http://pan.baidu.com/share/link?shareid=2536087943& ...

  5. Kali Linux上安装SSH服务

    安装 SSH 从终端使用 apt-get 命令安装 SSH 包: # apt-get update # apt-get install ssh 启用和开始使用 SSH 为了确保安全 shell 能够使 ...

  6. Windows安装pycrypto失败记录

    Windows 10家庭中文版,Python 3.6.4, 180824测试前端加密文本在后台揭秘,查询后发现,可以使用pycrypto模块实现,那么,安装它(pip),结果安装失败了. 本文暂时记录 ...

  7. 转:Vue-cli proxyTable 解决开发环境的跨域问题

    转:http://www.jianshu.com/p/95b2caf7e0da 和后端联调时总是会面对恼人的跨域问题,最近基于Vue开发项目时也遇到了这个问题,两边各自想了一堆办法,查了一堆资料,加了 ...

  8. JVM指令详解(上)

    指令码    助记符                            说明 0x00         nop                                什么都不做 0x01  ...

  9. tensorflow-作用域

    变量名字由两部分组成:scope/变量name. name 参数才是对象的唯一标识. 1.tf.name_scope() Graph中保存着一个属性_name_stack(string类型),_nam ...

  10. HTML5练习4

    1.菜单条 主要代码 <!doctype html> <html> <head> <meta charset="utf-8"> &l ...