Asp.net core實現(xiàn)PushStream視頻流推送
最近用asp.net core webapi實現(xiàn)了一個實時視頻流的推送功能,在Asp.net中,這個是通過PushStreamContent來實現(xiàn)的。
基于對asp.net core的知識,隨手寫了一個(要求控制器繼承自Controller基類)
[HttpGet] public async Task Get() { var response = HttpContext.Response; response.ContentType = "text/html"; response.StatusCode = 200; var stream = HttpContext.Response.Body; while (true) { await Task.Delay(1000); var content = DateTime.Now + @" "; var data = Encoding.Default.GetBytes(content); await stream.WriteAsync(data, 0, data.Length); await stream.FlushAsync(); } }
使用chrome調(diào)試這個接口時,發(fā)現(xiàn)它確實行之有效的將當(dāng)前的時間推送到了瀏覽器的頁面上。
然而,當(dāng)我進(jìn)一步的調(diào)試它的異常情況時,發(fā)現(xiàn)就算將chrome關(guān)掉,這個程序卻依然在繼續(xù)運(yùn)行。從調(diào)試器中看到stream的狀態(tài)為Aborted,已經(jīng)識別到位終止的流了。
并且從VS的調(diào)試窗口也能看到異常信息:
但下面這兩行就是不拋異常:
await stream.WriteAsync(data, 0, data.Length); await stream.FlushAsync();
單單從接口的實現(xiàn)角度上來看,這個已經(jīng)不合理了。這是一個很大的坑,功能看上去還是正確的,沒有詳細(xì)調(diào)試還看不出來。一個不留神就踩上了。不知道微軟為什么要這么設(shè)計。
埋怨歸埋怨,問題還是要解決的。我查看了下FileStreamResult的源碼,發(fā)現(xiàn)它是靠HttpContext.RequestAborted來判斷客戶端是否終止了的。這是一個CancellationToken類型的對象,當(dāng)客戶端連接斷開后,它就處于被取消的狀態(tài)。
知道原因后,就可以知道如何修改我的程序了。
[HttpGet] public async Task Get() { var cancel = HttpContext.RequestAborted; var response = HttpContext.Response; response.ContentType = "text/html"; response.StatusCode = 200; var stream = HttpContext.Response.Body; while (true) { cancel.ThrowIfCancellationRequested(); await Task.Delay(1000, cancel); var content = DateTime.Now + @" "; var data = Encoding.Default.GetBytes(content); await stream.WriteAsync(data, 0, 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 = 200; 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(1000, cancel); var content = DateTime.Now + @"<br>"; var data = Encoding.Default.GetBytes(content); await stream.WriteAsync(data, 0, data.Length, cancel); await stream.FlushAsync(cancel); } }
到此這篇關(guān)于Asp.net core返回PushStream的文章就介紹到這了。希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
在?Net7.0?環(huán)境下如何使用?RestSharp?發(fā)送?Http(FromBody和FromForm)請求
這篇文章主要介紹了在?Net7.0?環(huán)境下使用?RestSharp?發(fā)送?Http(FromBody和FromForm)請求,今天,我就兩個小的知識點,就是通過使用?RestSharp?訪問?WebAPI,提交?FromBody?和?FromForm?兩種方式的數(shù)據(jù),還是有些區(qū)別的,本文結(jié)合實例代碼介紹的非常詳細(xì),需要的朋友參考下吧2023-09-09EFCore 通過實體Model生成創(chuàng)建SQL Server數(shù)據(jù)庫表腳本
這篇文章主要介紹了EFCore 通過實體Model生成創(chuàng)建SQL Server數(shù)據(jù)庫表腳本的示例,幫助大家更好的理解和學(xué)習(xí)使用.net框架,感興趣的朋友可以了解下2021-03-03ASP.net 頁面被關(guān)閉后,服務(wù)器端是否仍然執(zhí)行中?
當(dāng)一個正在執(zhí)行中的ASPX頁面執(zhí)行到一半的時候,瀏覽器中你關(guān)閉了這個頁面,服務(wù)器端對應(yīng)的這個頁面的代碼仍然在執(zhí)行么?2008-08-08asp.net下使用DbProviderFactories的數(shù)據(jù)庫操作類
項目開發(fā)中用到VB.NET開發(fā),參考網(wǎng)上的資料,自己寫了數(shù)據(jù)庫操作類。2010-06-06visual studio 2019使用net core3.0創(chuàng)建winform無法使用窗體設(shè)計器
這篇文章主要介紹了visual studio 2019使用net core3.0創(chuàng)建winform無法使用窗體設(shè)計器,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-03-03