ASP.NET Coreで応答を適切にストリーミングする方法は?次のようなコントローラーがあります(PDATED CODE):
[HttpGet("test")]
public async Task GetTest()
{
HttpContext.Response.ContentType = "text/plain";
using (var writer = new StreamWriter(HttpContext.Response.Body))
await writer.WriteLineAsync("Hello World");
}
Firefox/Edgeブラウザショー
こんにちは世界
、Chrome/Postmanはエラーを報告します:
ローカルホストページが機能していません
localhostが予期せず接続を閉じました。
ERR_INCOMPLETE_CHUNKED_ENCODING
追伸大量のコンテンツをストリーミングしようとしているため、事前にContent-Lengthヘッダーを指定できません。
ダウンロードしたファイルのようにブラウザに表示される応答をストリーミングするには、FileStreamResult
を使用する必要があります。
[HttpGet]
public FileStreamResult GetTest()
{
var stream = new MemoryStream(Encoding.ASCII.GetBytes("Hello World"));
return new FileStreamResult(stream, new MediaTypeHeaderValue("text/plain"))
{
FileDownloadName = "test.txt"
};
}
以前に_Response.Body
_に書き込んだ場合でも、null
またはEmptyResult()
(これらは同等)を返すことができます。メソッドがActionResult
を返すと、他のすべての結果も簡単に使用できるようになります(例:BadQuery()
)。
_[HttpGet("test")]
public ActionResult Test()
{
Response.StatusCode = 200;
Response.ContentType = "text/plain";
using (var sw = new StreamWriter(Response.Body))
{
sw.Write("something");
}
return null;
}
_
私もこれを行う方法を疑問に思っていた、と元の質問のコードがASP.NET Core 2.1.0-rc1-final
、Chrome(および他のいくつかのブラウザー)もJavaScriptアプリケーションも、そのようなエンドポイントで失敗しません。
追加したいマイナーなことは、StatusCodeを設定し、応答Streamを閉じて応答を満たすことです。
[HttpGet("test")]
public void Test()
{
Response.StatusCode = 200;
Response.ContentType = "text/plain";
using (Response.Body)
{
using (var sw = new StreamWriter(Response.Body))
{
sw.Write("Hi there!");
}
}
}
この質問は少し古いですが、私がやろうとしていたことに対して、どこにも良い答えを見つけることができませんでした。トリックは、書き込みたいコンテンツのチャンクごとに新しいStreamWriterを開くことです。次の手順を実行します。
[HttpDelete]
public void Content()
{
Response.StatusCode = 200;
Response.ContentType = "text/html";
// the easiest way to implement a streaming response, is to simply open a new stream writer every time
// you have new data to write. When the writer is closed, the data will be sent to the client.
foreach (var item in new int[] { 1, 2, 3, 4, })
{
using (var sw = new StreamWriter(Response.Body))
{
Thread.Sleep(1000);
sw.Write($"<p>Hi there {item}!</p>");
}
};
}
次のコマンドを使用してcurlでテストできます:curl -NX DELETE <CONTROLLER_ROUTE>/content