在Asp.net core返回PushStream
最近用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的更多相关文章
- ASP.NET Core 返回 Json DateTime 格式
ASP.NET Core 返回 Json 格式的时候,如果返回数据中有DateTime类型,如何自定义其格式呢?配置如下: services.AddMvc().AddJsonOptions(opt = ...
- ASP.NET Core 返回文件、用户下载文件,从网站下载文件,动态下载文件
ASP.NET Core 中,可以在静态目录添加文件,直接访问就可以下载.但是这种方法可能不安全,也不够灵活. 我们可以在 Controller 控制器中 添加 一个 Action,通过此Action ...
- ASP.Net Core 返回的json数据,自定义日期格式
//代码位置:Startup.cs public void ConfigureServices(IServiceCollection services) { services.AddMvc() .Ad ...
- ASP.NET Core 如何实现404错误跳转到主页
假如用户在Web浏览器上敲错了URL,访问了ASP.NET Core站点下一个不存在的URL地址,那么默认情况下ASP.NET Core会返回给浏览器著名的404错误,那么有什么办法可以让ASP.NE ...
- 剖析ASP.NET Core(Part 4)- 调用MVC中间件(译)
原文:https://www.stevejgordon.co.uk/invoking-mvc-middleware-asp-net-core-anatomy-part-4 发布于:2017年5月环境: ...
- Asp.net Core WebApi 支持json/xml格式的数据返回
Asp.net core 在做webapi项目的时候,默认是只返回json格式的数据的,如果想要开启xml数据返回,需要在startup里配置如下: public void ConfigureServ ...
- Asp.net Core WebApi 返回JSON自动驼峰格式化问题
从今天开始,正式进入Asp.net Core的开发,估计最近一段时间会经常写博客了,记录学些Asp.net Core中遇到的各种坑. 第一个问题:通过core编写的webapi,默认返回的json会自 ...
- ASP.NET Core WebApi 返回统一格式参数(Json 中 Null 替换为空字符串)
相关博文:ASP.NET Core WebApi 返回统一格式参数 业务场景: 统一返回格式参数中,如果包含 Null 值,调用方会不太好处理,需要替换为空字符串,示例: { "respon ...
- ASP.NET Core WebAPI控制器返回类型的最佳选项
前言 从.NET Core 2.1版开始,到目前为止,控制器操作可以返回三种类型的WebApi响应.这三种类型都有自己的优点和缺点,但都缺乏满足REST和高可测性的选项. ASP.NET Core中可 ...
随机推荐
- 20155207王雪纯 2016-2017-2 《Java程序设计》第六周学习总结
20155207 2016-2017-2 <Java程序设计>第六周学习总结 教材学习内容总结 第10章 输入/输出 10.1 InputStream与OutputStream 10.1. ...
- Linux Timer定时器【转】
转自:https://www.jianshu.com/p/66b3c75cae81 timerfd为Linux为用户程序提供的定时器接口,该接口基于文件描述符,通过文件描述符的可读事件进行超时通知,且 ...
- js中apply的用法(转)
之一------(函数的劫持与对象的复制)关于对象的继承,一般的做法是用复制法: Object.extend见protpotype.js 的实现方法: Object.extend = function ...
- (转载)ibatis:解决sql注入问题
原文地址:http://blog.csdn.net/scorpio3k/article/details/7610973 对于ibaits参数引用可以使用#和$两种写法,其中#写法会采用预编译方式,将转 ...
- 【最简单的方法】js判断字符串是否为JSON格式(20180115更新)
前言 针对 “js判断字符串是否为JSON格式” 这个问题,在网上查了许多资料,都没找到自己想要的答案. 但是看到这个帖子<js判断字符串是否为JSON格式>后,突然灵光一闪,想到一种很简 ...
- 浅谈js设计模式之代理模式
代理模式是一种非常有意义的模式,在生活中可以找到很多代理模式的场景.比如,明星都有经纪人作为代理.如果想请明星来办一场商业演出,只能联系他的经纪人.经纪人会把商业演出的细节和报酬都谈好之后,再把合同交 ...
- Coursera台大机器学习技法课程笔记09-Decision Tree
这是我们已经学到的(除Decision Tree外) 下面是一个典型的decision tree算法,有四个地方需要我们选择: 接着介绍了一个CART算法:通过decision stump分成两类,衡 ...
- js时间格式化函数(兼容IOS)
* 时间格式化 * @param {Object} dateObj 时间对象 * @param {String} fmt 格式化字符串 */ dateFormat(dateObj, fmt) { le ...
- 第二届CCF软件能力认证
1. 相邻数对 问题描述 给定n个不同的整数,问这些数中有多少对整数,它们的值正好相差1. 输入格式 输入的第一行包含一个整数n,表示给定整数的个数. 第二行包含所给定的n个整数. 输出格式 输出一个 ...
- #CSS margin-top父元素下落
[我的解决方法] 给该父元素添加如下代码 border-top: 1px solid rgba(0,0,0,0); box-sizing:border-box; [原因] css2.1盒模型中规定的内 ...