Search code examples
asp.net-mvcimagesharp

Trying to return an image via MVC controller action after using ImageSharp resizing


I am trying to take an image, resize it with ImageSharp via image.Mutate, save it to a stream, and return the image as a file via mvc controller to an Angular client. This is my code I am using to alter the image:

    public static MemoryStream ImageResizeStream(byte[] data, int maxHeight, int maxWidth, bool keepIfLower, string extension)
    {
        var size = new ImageSize();
        using (var image = Image.Load(data))
        {
            size.Height = image.Height;
            size.Width = image.Width;
        }

        ImageSize newSize = ScaleSize(size, maxWidth, maxHeight);

        var newStream = new MemoryStream();
        try
        {
            using (var image = Image.Load(data))
            {
                image.Mutate(x => x
                    .Resize(newSize.Width, newSize.Height));
                image.Save(newStream, GetImageEncoder(extension));
            }
            return newStream;
        }
        catch (Exception exception)
        {
            Console.Write(exception.Message);
        }

        return null;
    }
    public class ImageSize
    {
      public ImageSize()
      {

      }

      public ImageSize(int width, int height)
      {
          Width = width;
          Height = height;
      }
      public int Height { get; set; }
      public int Width { get; set; }
    }

And this is the controller action code that uses it: (AlterImage is the class returning the stream)

    private FileStreamResult SetResult(SystemLogo logo)
    {
        var logoExtension = logo.FileName.Split('.').Last();

        var fileType = string.Empty;

        switch (logoExtension)
        {
            case "png":
                fileType = "image/png";
                break;
            case "jpg":
                fileType = "image/jpg";
                break;
            case "gif":
                fileType = "image/gif";
                break;
        }

        //var maxHeight = 38;
        //var maxWidth = 100;
        var newStream = AlterImage.ImageResizeStream(logo.Content, 38, 100, true, logoExtension);

        var result = File(newStream, fileType);
        return result;
    }

(I return this as the result of the action)

On the client, it is getting a 500 error that I have not been able to track as of yet. Is there something I am missing here?


Solution

  • You need to set the stream position to 0 when passing a stream to a FileResult.

    On top of that I can see some other issues (not related to your problem but not good either)

    • You don't need the ImageSize class. There's already a Size struct in the SixLabors.Primitives namespace that is a property of the Image<TPixel> class.

    • You're loading the image twice! You don't need to do that. Use the Size property inside the second using to calculate your new dimensions.

    • You're calculating the mimetypes and choosing the encoder manually. Image.Load has an overload that gives you an out IImageFormat parameter. That contains an encoder, extension, plus the mimetype.

    I'm curious about your SystemLogo class also. That the Content property is a byte[] strongly suggests to e you are using ToArray() somewhere when populating that object. If so, that's adding overhead you should try and avoid. Use streams to pass data instead.