I noticed that FileStreamResult
will call Stream.ReadAsync
looply and push datas to network stream until it returns 0.
But the http response header will be send to client after first time to call Stream.ReadAsync
when completed.
Now I need return a stream which generated by a long time process. I need return header before the stream have not generated.
Is it possible?
What's I tried:
First call ReadAsync
returns 0 will stop FileStreamResult
reading and dispose it.
Returns 1 will send a zero byte into stream and broken data.
That is I have to return some of data from the stream on the first call to ReadAsync
, even a byte, to tell service the stream can be read now, and it's time to return header to tell client this.
But the stream hasn't been generated yet and it's impossible for me to return any reliable data.
I can't return 0, it ends the connection.
CodePudding user response:
I'm actually not sure if there's a better solution to this, but I've managed to solve the issue by making a custom IActionResultExecutor<FileStreamResult>
, based off the default one used in ASP.NET Core:
public class CustomFileStreamResultExecutor : FileStreamResultExecutor
{
public CustomFileStreamResultExecutor(
ILoggerFactory loggerFactory)
: base(loggerFactory)
{
}
protected override async Task WriteFileAsync(
ActionContext context,
FileStreamResult result,
RangeItemHeaderValue? range,
long rangeLength)
{
// Ensure everything we have so far has been sent
await context.HttpContext.Response.Body.FlushAsync();
// Continue with the normal functionality from here on out
await base.WriteFileAsync(context, result, range, rangeLength);
}
}
And then we can register it before we call services.AddControllers();
(if you register it afterwards, ASP.NET Core will already have registered its own):
Services.AddSingleton<IActionResultExecutor<FileStreamResult>, CustomFileStreamResultExecutor>();
You can find the code for the default executor here.