Search code examples
asp.netasp.net-corerazorimagesharp

How do I write an image's MemoryStream to the page body?


I'm converting ASP.NET WebForms code to ASP.NET Core Razor pages which is new to me. I'm trying to retrieve an image MemoryStream from a business class (based on SixLabors awesome ImageSharp) and have the page render the JPEG -- no HTML, just the image. I intend to use this page elsewhere as an <img> src, like <img src="Render?imageID=42&mode=invert" />

In Render.cshtml.cs:

public class RenderModel : PageModel
{
    public void OnGet()
    {
        //snip

        Stream stream = new MemoryStream();

        using (Image image1 = Image.Load(imagePath))
        {
            SixLabors.ImageSharp.Formats.Jpeg.JpegEncoder encoder = new SixLabors.ImageSharp.Formats.Jpeg.JpegEncoder();
            encoder.Quality = 75;

            image1.Save(stream, encoder);
            //image.Save("/temp/xxx.jpg", encoder); //test to see image. it works
        }

        Response.Clear();
        //Response.Headers.ContentLength = stream.Length;
        Response.ContentType = "image/jpeg";
        Response.Body = stream;
    }
}

...but this is not working, I get:

System.InvalidOperationException: Response Content-Length mismatch: too few bytes written (0 of 135408).

135408 is the stream.Length.

I'm probably not doing this correctly in the ASP.NET Core/Razor way. Can anyone set me straight as to how to do this? Thanks!

EDIT: commenting out the Headers.ContentLength fixes the error. But now I get a broken-image icon in the browser. Closer...


Solution

  • You need to write to the Response.Body isntead of replacing it.

    stream.Seek(0, SeekOrigin.Begin);
    await stream.CopyToAsync(Response.Body);
    await Response.Body.FlushAsync();