Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamically Rendering asp:Image from BLOB entry in ASP.NET

Tags:

asp.net

What I want to achieve is this. I want to give the user the ability to upload an image file, store the image in BLOB in SQL Server, and then use this image as a logo in other pages of the site.

I have done this by using

   Response.Clear();
   Response.ContentType = "image/pjpeg";
   Response.BinaryWrite(imageConents);
   Response.End();

but to do this, I use a User control in the place where I want to show the image. I want to do it if possible using an asp:Image control, or even a pure old html image control. Is this possible?

like image 503
Nikos Steiakakis Avatar asked Aug 22 '08 06:08

Nikos Steiakakis


2 Answers

Add a 'Generic Handler' to your web project, name it something like Image.ashx. Implement it like this:

public class ImageHandler : IHttpHandler
{

    public void ProcessRequest(HttpContext context)
    {
        using(Image image = GetImage(context.Request.QueryString["ID"]))
        {    
            context.Response.ContentType = "image/jpeg";
            image.Save(context.Response.OutputStream, ImageFormat.Jpeg);
        }
    }

    public bool IsReusable
    {
        get
        {
            return true;
        }
    }
}

Now just implement the GetImage method to load the image with the given ID, and you can use

<asp:Image runat="server" ImageUrl="~/Image.ashx?ID=myImageId" /> 

to display it. You might want to think about implementing some form of caching in the handler too. And remember if you want to change the image format to PNG, you need to use an intermediate MemoryStream (because PNGs require a seekable stream to be saved).

like image 70
Fredrik Kalseth Avatar answered Oct 21 '22 07:10

Fredrik Kalseth


You can BASE64 encode the content of the image directly into the SRC attribute, however, I believe only Firefox will parse this back into an image.

What I typically do is a create a very lightweight HTTPHandler to serve the images:

using System;
using System.Web;

namespace Example
{  
    public class GetImage : IHttpHandler
    {

        public void ProcessRequest(HttpContext context)
        {
            if (context.Request.QueryString("id") != null)
            {
                Blob = GetBlobFromDataBase(id);
                context.Response.Clear();
                context.Response.ContentType = "image/pjpeg";
                context.Response.BinaryWrite(Blob);
                context.Response.End();
            }
        }

        public bool IsReusable
        {
            get
            {
                return false;
            }
        }
    }
}

You can reference this directly in your img tag:

<img src="GetImage.ashx?id=111"/>

Or, you could even create a server control that does it for you:

using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace Example.WebControl
{

    [ToolboxData("<{0}:DatabaseImage runat=server></{0}:DatabaseImage>")]
    public class DatabaseImage : Control
    {

        public int DatabaseId
        {
            get
            {
                if (ViewState["DatabaseId" + this.ID] == null)
                    return 0;
                else
                    return ViewState["DataBaseId"];
            }
            set
            {
                ViewState["DatabaseId" + this.ID] = value;
            }
        }

        protected override void RenderContents(HtmlTextWriter output)
        {
            output.Write("<img src='getImage.ashx?id=" + this.DatabaseId + "'/>");
            base.RenderContents(output);
        }
    }
}

This could be used like

<cc:DatabaseImage id="db1" DatabaseId="123" runat="server/>

And of course, you could set the databaseId in the codebehind as needed.

like image 38
FlySwat Avatar answered Oct 21 '22 08:10

FlySwat