How to make an image handler in NancyFx
Asked Answered
C

3

20

I'm struggling to output an Image from byte[] out of my database in NancyFX to a web output stream. I don't have sample code close enough to even show at this point. I was wondering if anyone has tackled this problem and could post a snippet? I basically just want to return image/jpeg from a byte array stored in my database and out put it to the web rather than a physical file.

Cheatham answered 23/1, 2013 at 6:10 Comment(0)
K
30

Just to build on @TheCodeJunkie's answer, you can build a "byte array response" very easily like this:

public class ByteArrayResponse : Response
{
    /// <summary>
    /// Byte array response
    /// </summary>
    /// <param name="body">Byte array to be the body of the response</param>
    /// <param name="contentType">Content type to use</param>
    public ByteArrayResponse(byte[] body, string contentType = null)
    {
        this.ContentType = contentType ?? "application/octet-stream";

        this.Contents = stream =>
            {
                using (var writer = new BinaryWriter(stream))
                {
                    writer.Write(body);
                }
            };
    }
}

Then if you want to use the Response.AsX syntax it's a simple extension method on top:

public static class Extensions
{
    public static Response FromByteArray(this IResponseFormatter formatter, byte[] body, string contentType = null)
    {
        return new ByteArrayResponse(body, contentType);
    }
}

Then in your route you can just use:

Response.FromByteArray(myImageByteArray, "image/jpeg");

You could also add a processor to use a byte array with content negotiation, I've added a quick sample of that to this gist

Kirstinkirstyn answered 23/1, 2013 at 8:14 Comment(3)
Thank you very much for expanding on the solution, it's exactly what I needed.Cheatham
Is there a way to make browser cache the byte array response of the request? So that the handler will not work again for the same url?Mariannamarianne
That's terrible, that cache's the bytes in memory. Can't you stream directly (using minimal memory)?Acerose
C
12

In your controller, return Response.FromStream with a stream of bytes of the image. It used to be called AsStream in older versions of nancy.

Get["/Image/{ImageID}"] = parameters =>
{
     string ContentType = "image/jpg";
     Stream stream = // get a stream from the image.

     return Response.FromStream(stream, ContentType);
};
Cabinda answered 20/2, 2015 at 7:43 Comment(3)
How are you supposed to close the source stream with this API? Terrible.Acerose
The source stream is disposed automatically later -github.com/NancyFx/Nancy/issues/786Acerose
You have to make sure that the stream position is set to the beginning of the stream: stream.Seek(0, SeekOrigin.Begin), since FromStream won't do it for you.Seacock
I
8

From Nancy you can return a new Response object. It's Content property is of type Action<Stream> so you can just create a delegate that writes your byte array to that stream

var r = new Response();
r.Content = s => {
   //write to s
};

Don't forget to set the ContentType property (you could use MimeTypes.GetMimeType and pass it the name, including extension) There is also a StreamResponse, that inherits from Response and provides a different constructor (for a bit nicer syntax you can use return Response.AsStream(..) in your route.. just syntax candy)

Inadvertent answered 23/1, 2013 at 6:52 Comment(2)
Thanks for help, I like the alternate solutions you presented.Cheatham
Looks like the property name changed to Contents.Kilauea

© 2022 - 2024 — McMap. All rights reserved.