Search code examples
imageresizer

ImageResizer and Images delivered as byte stream


We have an umbraco MVC website with which we are trying to use ImageResizer. In order to keep uploaded files out of a publicly accessible area, images are stored outside of the webroot and we use a controller to deliver them to browswer (e.g. an image url on a page would be something like <img src="/umbraco/surface/AttachmentSurface/ShowImage/999?" alt="Here there be an image, yarrr!">)

The ShowImage action is something like:

public ActionResult ShowImage(int id)
{
    using (DBContext db = new DBContext())
    {
        Attachment a = db.Attachments.FirstOrDefault(x.ID == id);
        if (a != null)
        {
            byte[] file = System.IO.File.ReadAllBytes(System.IO.Path.Combine(System.Configuration.ConfigurationManager.AppSettings["UploadPath"], a.Path, a.FileName));
            return this.File(file, a.MimeType);
        }
    }
}

If we use the URL API on a publicly accessible image (e.g. <img src="/images/kitty.jpg?width=33&height=33&mode=crop" alt="Here there be kitties, yarrr!">), then everything works as expected.

However, we've tried using the URL API to resize our images delivered by the controller to no avail (e.g. <img src="/umbraco/surface/AttachmentSurface/ShowImage/999?width=33&height=33&mode=crop" alt="Here there be an image, yarrr!">).

Is the only way around this to use the Managed API and resize the image before delivering? I seem to remember the documentation saying something to the effect that it's a bad idea to use it from within an MVC Action...

Thanks for any help.


Solution

  • ImageResizer doesn't operate as middleware, unfortunately, as middleware can't access the right resources in order to do a good job. It controls the request from beginning to end, and tries to integrate smoothly with existing authentication, URL rewrite, and CMS modules. That's why it doesn't work on an MVC action. It wouldn't be able to cache to disk, and it would have a severe performance overhead from double-buffering.

    If you're just trying to block access to original files, you could do that in a variety of ways without moving the files outside of the root (UrlAuthorization, AuthorizeRequest event, disabling handlers for that folder, etc).

    If you want to control where the images come from, you should implement an IVirtualImageProvider class. ImageResizer does include an IVirtualImageProvider plugin (named VirtualFolder) that can provide access to external/off root files. If your needs are basic, give that a try, and drop the MVC action.