3

I am trying to send a large file using FileStreamResult -

return new UnbufferedFileStreamResult(new FileStream(apiResponse.url, FileMode.Open, FileAccess.Read), "text/csv") { FileDownloadName = new FileInfo(apiResponse.url).Name };

The UnbufferedFileStreamResult is:

public class UnbufferedFileStreamResult : FileStreamResult {
    public UnbufferedFileStreamResult(Stream fileStream, string contentType) : base(fileStream, contentType) {

    }

    public override void ExecuteResult(ActionContext context) {
        context.HttpContext.DisableOutputBuffering();
        base.ExecuteResult(context);
    }
}

This seems to work for files up to a certain size, but if they get too big I get the following exception:

System.IO.IOException: Stream was too long.
   at System.IO.MemoryStream.Write(Byte[] buffer, Int32 offset, Int32 count)
   at System.IO.MemoryStream.WriteAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken)
--- End of stack trace from previous location where exception was thrown ---
   at Microsoft.AspNetCore.Http.Extensions.StreamCopyOperation.CopyToAsync(Stream source, Stream destination, Nullable`1 count, Int32 bufferSize, CancellationToken cancel)
   at Microsoft.AspNetCore.Mvc.Infrastructure.FileResultExecutorBase.WriteFileAsync(HttpContext context, Stream fileStream, RangeItemHeaderValue range, Int64 rangeLength)
   at Microsoft.AspNetCore.Mvc.Infrastructure.FileStreamResultExecutor.ExecuteAsync(ActionContext context, FileStreamResult result)
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeResultAsync(IActionResult result)
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextResultFilterAsync[TFilter,TFilterAsync]()
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResultExecutedContext context)
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.ResultNext[TFilter,TFilterAsync](State& next, Scope& scope, O

So it appears that FileStreamResultExecutorBase is copying my file stream into a memory stream before it goes to the http output stream. My questions are 1) why is it doing this, 2) how can I prevent this behavior, and 3) are there implementations of results like FileStreamResult that can read directly from the input stream to the output stream without copying to memory first?

tacos_tacos_tacos
  • 10,277
  • 11
  • 73
  • 126
  • _So it appears that FileStreamResultExecutorBase is copying my file stream into a memory stream before it goes to the http output stream_. What makes you think so? [source](https://github.com/aspnet/AspNetCore/blob/master/src/Http/Http.Extensions/src/StreamCopyOperation.cs#L36) – Tseng Dec 18 '18 at 18:51
  • 3
    Do you have some funky stuff/middleware running, which replaces your `request.Body` stream (only explaination)? – Tseng Dec 18 '18 at 18:57
  • @Tseng, yep that was it. – tacos_tacos_tacos Jan 14 '19 at 00:33

0 Answers0