Kirk Evans Blog

.NET From a Markup Perspective

Web App Design: Avoid Writing to Disk, Part 2

Web App Design: Avoid Writing to Disk, Part 2

  • Comments 5

Dasher left an interesting comment to my previous post on avoiding writing to disk:

Don't you hit the reverse problem with needing to save the image to a file for displaying in a webpage?

Nope, you can do the reverse just as easily.  The trick is figuring out how to get the stream from the database and applying it to the ASP.NET Image control. 

A simple solution is to create an HttpHandler that will serve as a dynamic image generator.  To do this, create a Generic Handler (.ashx) and add the following code:

<%@ WebHandler Language="C#" Class="ImageHandler" %>

using System;
using System.Web;
using System.Drawing.Imaging;
using System.Data.SqlClient;
using System.IO;

public class ImageHandler : IHttpHandler 
{
    private HttpResponse _response;
    
    private HttpResponse Response
    {
        get { return _response; }
    }
    
    public void ProcessRequest (HttpContext context) 
    {
        _response = HttpContext.Current.Response;
        
        Response.ContentType = "image/pjpeg";
        SqlConnection cn = new SqlConnection(
        @"Database=AdventureWorks;Server=(local);
     Integrated Security=true;");
        cn.Open();
        SqlCommand select = new SqlCommand(@"
    SELECT      LargePhoto
    FROM         Production.ProductPhoto
    WHERE     (ProductPhotoID = 182)", cn);

        try
        {
            byte[] imageBytes = (byte[])select.ExecuteScalar();
            MemoryStream mem = new MemoryStream(imageBytes);
            System.Drawing.Image image = System.Drawing.Image.FromStream(mem);
            image.Save(Response.OutputStream, ImageFormat.Jpeg);
        }
        catch (SqlException oops)
        {
            Response.ContentType = "text/html";
            Response.Write(oops.ToString());
        }
        finally
        {
            select.Dispose();
            cn.Close();
            cn.Dispose();
        }
    }
 
    public bool IsReusable {
        get {
            return false;
        }
    }
}

I saved my generic handler as "ImageHandler.ashx".  To use the image handler, simply reference it as the ImageUrl from the image control that you want to use:

<asp:Image ID="Image1" ImageUrl="~/ImageHandler.ashx" runat="server" />

Admittedly, this is a pretty simple implementation.  I leave it as an exercise for the reader to leverage the ASP.NET Cache to cache requests for the image based on ID and return the image from the cache rather than hit the database.  You might also implement security for the requested image, checking to see if the current user has access to the image data or not.

Funny, but I just realized I had a case of deja vu, since I had gone through this same conversation regarding base64 encoding an image and base64 decoding an image.

  • Good idea using the handler :)
  • You're not hitting the disk, but you're hitting the server memory now ;) (loading the entire image in-memory before sending to the output, in the ExecuteScalar call).

    A better approach is to stream the data in chunks to the client, as explained in http://clariusconsulting.net/blogs/kzu/archive/2003/08/27/74.aspx (wow... it's been 2.5 years already!!)

    Cheers buddy!
  • Awhile back, I posted about creating an image handler to render images stored in a database .&#160; Someone

Page 1 of 1 (5 items)
Leave a Comment
  • Please add 2 and 4 and type the answer here:
  • Post
Translate This Page
Search
Archive
Archives