Click here to Skip to main content
15,885,032 members
Articles / Web Development / ASP.NET

Generic Image Handler Using IHttpHandler

Rate me:
Please Sign up or sign in to vote.
4.61/5 (17 votes)
13 Mar 2009Public Domain2 min read 101.4K   2.6K   34   10
Example of an HttpHandler to handle image URLs and hide server mapped paths from users. This can also be used to generate thumbnails of any size.

Introduction

Here, I want to share a nice way to display images on web pages using an HttpHandler. Using this method, we can hide an image's server mapped path from the user as in the image shown above. Also, the same image handler can be used to generate thumbnails of variable dimensions passed using the querystring.

Understanding the code

The heart of this generic image handler is the ImageHandler class which implements the IHttpHandler and IRequiresSessionState interfaces.

IRequiresSessionState specifies that the target HTTP handler requires read and write access to session-state values. This is a marker interface and has no methods.

The IHttpHandler interface's ProcessesRequest method is implemented in this handler where all the image processing logic goes. Every time the handler is invoked, the handler checks for parameters passed through the query string, generates the corresponding image response, and writes it to current context. For further requests of the same image, the response is saved in a hash table, in the session. The same image handler can be used for multiple groups of images. In this example, I have used it for two groups: User Images and Status Images. A Dictionary object map is used to map different image groups with the strict filename logic used here.

C#
public void ProcessRequest(HttpContext context)
{
    if (context.Request["id"] != null  && 
        context.Request["tName"] != null)
    {
        Dictionary<string,> map = new Dictionary<string,>();
        map.Add("UserImage", "user");
        map.Add("StatusImage", "status");
        if (context.Request["xlen"] != null)
        {
            XLen = context.Request["xlen"].ToString();
        }
        if (context.Request["ylen"] != null)
        {
            YLen = context.Request["ylen"].ToString();
        }
        string id =  context.Request["id"].ToString();
        string tName = context.Request["tName"].ToString();
        Hashtable ht;
        if (context.Session[tName] != null)
        {
            ht = (Hashtable)context.Session[tName];
            if (!ht.ContainsKey(id))
            {
                FileStream fInfo = new FileStream(context.Server.MapPath("images/" + 
                                   map[tName].ToString() + id + ".jpg"), FileMode.Open);
                byte[] bFile ;
                bFile = GenerateThumbnail(fInfo, XLen, YLen);
                ht.Add(id, bFile);
                fInfo.Close();
            }
        }
        else
        {
            ht = new Hashtable();
            FileStream fInfo = new FileStream(context.Server.MapPath("images/" + 
                               map[tName].ToString() + id + ".jpg"), FileMode.Open);
            byte[] bFile ;
            bFile = GenerateThumbnail(fInfo, XLen, YLen);
            ht.Add(id, bFile);
            context.Session[tName] = ht;
            fInfo.Close();
        }
        Byte[] arrImg = (byte[])ht[id];
        context.Response.Clear();
        context.Response.ContentType = "image/jpeg";
        context.Response.BinaryWrite(arrImg);
        context.Response.End();
    }
}

A simple thumbnail generation routine is used to generate thumbnails of the desired size. It uses the System.Drawing.Image class' GetThumbnailImage() method to generate thumbnails.

C#
private byte[] GenerateThumbnail(Stream fStream, string xLen, string yLen)
{
    Image img = Image.FromStream(fStream);
    Image thumbnailImage = img.GetThumbnailImage(int.Parse(xLen),int.Parse(yLen), 
          new Image.GetThumbnailImageAbort(ThumbnailCallback), IntPtr.Zero);
            
    MemoryStream imageStream = new MemoryStream();
    thumbnailImage.Save(imageStream, System.Drawing.Imaging.ImageFormat.Jpeg);

    byte[] imageContent = new Byte[imageStream.Length];
    imageStream.Position = 0;
    imageStream.Read(imageContent, 0, (int)imageStream.Length);
    return imageContent;
}

Using the code

The web application is informed of the HttpHandler using the web.config.

XML
<add type="ImageHandlerLib.ImageHandler, ImageHandlerLib" 
     path="ImageHandler.aspx" verb="*" />

The default thumbnail size has been set as 110X110 in the ImageHandler class. This dimension is used unless both the attributes are sent via the query string to the handler.

Displaying an image this way hides the server mapped path that we would normally use like "<img src="image/user1.jpg" />, which gives away our directory structure of the virtual directory. Instead, we use a generic URL and pass parameters requesting specific images in the query string. The general format for queering any image using the above handler is:

src = "ImageHandler.aspx?tName=[groupname]&id=[idnumber]"

Scope

To further make the image handler's URLs secure so that nobody else can directly access your URLs in their own applications, you can implement your own security checking code in the beginning of the ProcessRequest method.

Also, instead of the strict file naming logic (i.e., strict filename formats for image files) that I have used in this example, the code can be further customized to have file names of image files passed as query string parameters. That should make this image handler really generic. :)

History

  • Created: 12 March 2009.

License

This article, along with any associated source code and files, is licensed under A Public Domain dedication


Written By
Software Developer (Senior) Geometric
India India
B.E. in Information Technology
MCTS(.NET 2.0 )

Comments and Discussions

 
QuestionDeployment of the solution Pin
Member 839420730-Jun-17 20:50
Member 839420730-Jun-17 20:50 
QuestionDoesn't work on IIS7 Pin
rafaelverisys11-Apr-13 3:37
rafaelverisys11-Apr-13 3:37 
AnswerRe: Doesn't work on IIS7 Pin
rafaelverisys11-Apr-13 4:01
rafaelverisys11-Apr-13 4:01 
GeneralRe: Doesn't work on IIS7 Pin
mmaurox27-May-13 3:50
mmaurox27-May-13 3:50 
GeneralMy vote of 5 Pin
khalleo7-Feb-13 4:01
khalleo7-Feb-13 4:01 
QuestionThis is very good article. Pin
Jayesh Sorathia27-Jan-13 20:59
Jayesh Sorathia27-Jan-13 20:59 
GeneralStoring images in Session is a terrible idea Pin
FerretOfWrath25-Aug-09 5:58
FerretOfWrath25-Aug-09 5:58 
This solution does not scale. Let the web server handle caching of static content. Use mechanisms like output caching, etc. If the app ever moves to use Session state database, this solution will definitely create numerous session deadlocks as the app increases in load. This solution will cause all of session to be loaded in full for every image on every page as well. Session in general should be avoided like the plague for any app that wants to scale, and storing images in there is going to make it much worse very quickly.

Other than the Session storage part, the article is fine Smile | :)
GeneralRe: Storing images in Session is a terrible idea Pin
Vikcia4-Jun-12 21:20
Vikcia4-Jun-12 21:20 
GeneralMy vote of 2 Pin
Giga778-Apr-09 12:51
Giga778-Apr-09 12:51 
GeneralGood One Pin
Member 306113315-Mar-09 21:35
Member 306113315-Mar-09 21:35 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.