2

I was wondering how to send an (in my case) SqlFileStream directly to the client through our Nancy-API without loading the stream in memory.

So far I succeeded in passing the stream, but Nancy's StreamResponse copies the sourcestream (=SqlFileStream) to the outputstream which causes a massive memory increase. Where I would just like it to send the stream through.

I made this work in WebApi where WebApi was registered in the Owin-pipeline. No memory increase is noticeable, which is great when we are talking about pretty big streams (>100MB). But of course I'd rather stick to one API-application-framework if possible.

Any tips?

Guillaume Schuermans
  • 906
  • 2
  • 12
  • 28

1 Answers1

1

I think I found a solution. It wasn't too difficult to do in the end.

I created a custom Nancy.Response => FlushingStreamResponse. Passing it a stream and a mimetype, results in immediate streaming to the client when this is the result of our GET.

public class FlushingStreamResponse : Response
{
    public FlushingStreamResponse(Stream sourceStream, string mimeType)
    {
        Contents = (stream) =>
        {
            var buffer = new byte[16 * 1024];
            int read;
            while ((read = sourceStream.Read(buffer, 0, buffer.Length)) > 0)
            {
                stream.Write(buffer, 0, read);
                stream.Flush();
            }
            sourceStream.Dispose();
        };

        StatusCode = HttpStatusCode.OK;
        ContentType = mimeType;
    }
}
Guillaume Schuermans
  • 906
  • 2
  • 12
  • 28
  • It can be done a bit simpler (and more idiomatic) using simple `Contents = ostream => { sourceStream.CopyTo(ostream); ostream.Flush(); }` – kostix Jul 24 '15 at 15:32