Search code examples
asp.netms-accesswebms-access-2007

In a website running ASP.NET, how can I display an image stored in an MS Access 2007 Attachment Type


BACKGROUND:
MS Access 2007 added an attachment field type, where images can be stored.
I am building a website using ASP.Net and the .NET framework 4

So, without using Silverlight, what is the easiest way to retrieve the image from the Access database on the server, and use as source for an Image control?

As a simple example:
In an ESL website for children, clicking on a "A", would display an apple; "B" a bear, etc

NOTE: This is an A2007/A2010 attachment field, not a binary object


Solution

  • You could read the image out of the database as a binary blob. This would be read out as a byte[] array. That byte[] could then be sent to the browser using a Response.BinaryWrite and a content-type of image/(type) - jpg/png/gif.

    The call would look something like:

    <img src="showmyimages.aspx?image=id" />
    

    And the code would look a little like:

    result = myWebService.GetImage(id);

    if (result != null) && result.Length > 0
    {
        Context.Response.ClearContent();
        Context.Response.ClearHeaders();
        Context.Response.ContentType = "image/gif";
        Context.Response.AddHeader("Content-Length", result.Length.ToString(System.Globalization.CultureInfo.CurrentCulture));
        Context.Response.AddHeader("content-disposition", String.Format("inline; filename={0}.gif", filename));
        Context.Response.BinaryWrite(result);
        Context.Response.End();
    }
    

    This disguises the filename of the image a little bit, but it allows the binary read directly from the database without having a permanent image on disk.

    EDIT:

    Everything I've read about the attachment field is that it stores as direct binary in the database just as it would if it were saving directly to a file. I haven't attempted to write any code to this effect, but it is conceivable that no conversion is necessary if the binary data can be fed into a StreamReader, possibly even making use of WebResponse.GetResponseStream()

    EDIT:

    I was able to implement a handler using the following code that actually pulled the binary data from the attachment field (which can be verified in the debugger), however there appears to be an encoding involved that is not built in. The key seems to be the select statement that retrieves fldImage.FileData.

    public void ProcessRequest(HttpContext context)
            {
    
                string qry = "SELECT [Image], ID, [Images.Image.FileData] AS FileData, ";
                qry += "[Images.Image.FileName] AS FileName, [Images.Image.FileType] AS FileType";
                qry += " FROM Images WHERE (ID = 1)";
                string connect = @"Provider=Microsoft.ACE.OLEDB.12.0;Persist Security Info=False;Data Source=##PathToDB##\Database1.accdb";
    
                using (OleDbConnection conn = new OleDbConnection(connect))
                {
                    if (context.Request.QueryString["id"] != null)
                    {
    
                        OleDbCommand cmd = new OleDbCommand(qry, conn);
                        cmd.Parameters.AddWithValue("ID", context.Request.QueryString["id"]);
                        conn.Open();
                        using (OleDbDataReader rdr = cmd.ExecuteReader())
                        {
                            if (rdr.HasRows)
                            {
                                rdr.Read();
                                context.Response.ClearContent();
                                context.Response.ClearHeaders(); 
                                context.Response.ContentType = "image/" + rdr["FileType"];
    
                                byte[] result = Encoding.UTF8.GetBytes(rdr["FileData"].ToString());
    
                                context.Response.AddHeader("Content-Length",
                                    result.Length.ToString(System.Globalization.CultureInfo.CurrentCulture)); 
                                context.Response.AddHeader("content-disposition", 
                                    String.Format("attachment; filename={0}", rdr["FileName"]));
                                context.Response.BinaryWrite(result);
                                context.Response.End();
                            }
                        }
                    }
                }
    
            }
    

    There are also some methods that are located in the Microsoft Office Interop library described at the MSDN Access Blog that may be of use. They describe loading and saving files, but it looks as if they may also be able to perform the same actions directly to stream objects. The reference is Microsoft.Office.Interop.Access.Dao. When adding it, go to the COM tab and look for Microsoft Office 12.0 Access Database Engine Objects Library. I haven't tested this "straight to stream" theory.