Image thumbnail Html helper with image caching for the perforance
Creating image thumbnail with caching in MVC
Creating image thumbnail on the fly is pretty easy in ASP.NET whether you are still using WebForms or MVC. There is even a methods introduced in .NET 4.5 framework for generating thumbnail image from a Bitmap class instance.
You can easily create and action in a controller and generate and return thumbnail image on the fly. The problem is that Bitmap object takes a big chunk of memory when instantiated. If you are generating thumbnail on the fly, a big piece of memory will be taken on every request.
Although memory used by Bitmap instance will be released after request, this might be a bottle neck for you application under heavy traffic. Basically you are using processor power to return a thumbnail of a file which is probably generated for some other request. This means you will create instances of the same bitmap but for different requests, which is a bit waste of processor power.
Nice thing would be to store this generated bitmap as a file and return only file previously generated to all of the requests.
I have created a small HtmlHelper which does this
public static class HtmlHelpers { public static MD5 md5 = MD5.Create(); public static IHtmlString HtmlImageThumbnail(string imagePath, int width, int height, string alt = null, string @class = null) { return HtmlImageThumbnail(imagePath, new Size(width, height), alt, @class); } public static IHtmlString HtmlImageThumbnail(string imagePath, Size size, string alt = null, string @class = null) { var cacheFolder = "/ImageCache/"; var context = HttpContext.Current; var path = context.Server.MapPath(imagePath); var hashName = string.Concat(GetMd5Hash(string.Concat(path.Trim().ToLower(), "-", size.Width, "x", size.Height)), Path.GetExtension(imagePath).ToLower()); var cachedImagePath = context.Server.MapPath(Path.Combine(cacheFolder, hashName)); if (!File.Exists(cachedImagePath) && File.Exists(path)) { using (Bitmap bmp = new Bitmap(path)) { bmp.GetThumbnailImage(size.Width, size.Height, null, IntPtr.Zero).Save(cachedImagePath); } } var src = string.Concat(cacheFolder, hashName); XElement imgTag = new XElement("img", new XAttribute("src", src), new XAttribute("alt", !String.IsNullOrWhiteSpace(alt) ? alt : string.Empty), new XAttribute("class", !String.IsNullOrWhiteSpace(@class) ? @class : string.Empty)); return new HtmlString(imgTag.ToString()); } private static string GetMd5Hash(string input) { byte[] data = md5.ComputeHash(Encoding.UTF8.GetBytes(input)); StringBuilder sBuilder = new StringBuilder(); for (int i = 0; i < data.Length; i++) { sBuilder.Append(data[i].ToString("x2")); } return sBuilder.ToString(); } }
For generating thumbnail I used GetThumbnail methods on the Bitmap class instance, which is not my favorite, but for the sample purposes, this will work just fine. I prefer using some method I developed some time ago which you can find in this article on my blog.
These HtmlHelper is a part of mini project hosted on Github so you can fork it or download a source code to include in your project.
It can be easily used in any MVC Razor view just like any other HtmlHelper.
@WebOptimization.HtmlHelpers.HtmlImageThumbnail("/images/pebbles.jpg", 200, 200)
References
- http://dejanstojanovic.net/aspnet/2014/april/bitmap-manipulation-extension-methods/
- https://github.com/dejanstojanovic/HtmlOptimization
Disclaimer
Purpose of the code contained in snippets or available for download in this article is solely for learning and demo purposes. Author will not be held responsible for any failure or damages caused due to any other usage.
Comments for this article