SQL Database Image Storage & Easy Thumbnails






4.82/5 (58 votes)
Jan 6, 2007
7 min read

473630

8946
Shows how to store images in SQL Database Image Storage & create Thumnails easiliy from
Introduction
A while ago I needed to store some images within a database as part of a project. For a second task I also wanted to create thumbnails of the stored image data at varying sizes for an ASP.NET application that was part of my overall project.
This article will demonstrate how to store and retrieve image data from an SQL database, and shall also demonstrate how to create thumbnail images of this SQL database stored image data.
The Database
Why should we use a database and not just have the images within a virtual folder under the main ASP.NET folder? Well there are several reasons why it might be good to store images in a database, such as
- If the images binary data is stored in a database table, we have all the data required to make the image any size we want, and it will always look like the orginal image
- If the images binary data is stored in a database table, when we back the database up, we have also backed up all the users images
I am not saying this is the only way to go, its simply one way. As I say its something I had to do for a project, so I thought I would share what I found with you lot.
So what does the database look like.
It simply contains one table called tbl_image
which can be setup using the following script (contained within the object creation script at the top of this article)
CREATE TABLE [dbo].[tbl_image] (
[img_pk] [int] IDENTITY (1, 1) NOT NULL ,
[img_data] [image] NOT NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
As can be seen, its a very simply table. We simply store the images primary key (img_pk
) as an int type column, and the image data (img_data
) as an image type column. This is all fairly easy isn't it?
So how do we get data in / out of this table. I have actually written three stored procedures (contained within the object creation script at the top of this article), but most of this could actually be done with standard SQL command strings. That I'll leave up to you.
Let's have a look at the three stored procedures shall we, they are quite easy, in fact I think the comments at the top pretty much explain them in enough detail. So I won't bore you with any more explanatory words, as it's clear, isn't it?
sp_AddImage
/*
======================================================================
NAME : sp_AddImage
DESCRIPTION :
Creates a new image within the tbl_Image table, and returns the ID for
the newly inserted image.
Inserts a new image into the tbl_Image table, using the parameteres
provided. The IMAGE item is expected to be a binary[] array of data
that respresents the image in its entirety.
If the insertion is successful the newly inserted image primary key is
returned, in the output parameter @img_pk
INPUT PARAMETERS :
NAME: DATATYPE:
@img_data IMAGE
OUTPUT PARAMETERS :
NAME: DATATYPE:
@img_pk INT
RETURNS :
Nothing
======================================================================
*/
CREATE PROCEDURE [sp_AddImage]
(
@img_pk INT OUTPUT ,
@img_data IMAGE
)
AS
INSERT INTO tbl_Image ( img_data)
VALUES ( @img_data )
IF @@ROWCOUNT=1
SET @img_pk=@@IDENTITY
GO
sp_GetImageByID
/*
======================================================================
NAME : sp_GetImageByID
DESCRIPTION :
Returns a binary[] array which represents the image, whos primary key is equal
to the @img_pk input parameter
INPUT PARAMETERS :
NAME: DATATYPE:
@img_pk INT
RETURNS :
A binary[] array which represents the image, whos primary key is equal
to the @img_pk input parameter
======================================================================
*/
CREATE PROCEDURE [sp_GetImageByID]
(
@img_pk INT
)
AS
SELECT img_data FROM tbl_Image
WHERE img_pk=@img_pk
GO
sp_GetImages
/*
======================================================================
NAME : sp_GetImages
DESCRIPTION :
Returns a DataSet containing all the stored images
RETURNS :
A DataSet containing all the stored images
======================================================================
*/
CREATE PROCEDURE [sp_GetImages]
AS
SELECT * FROM tbl_Image
GO
The Web Application
Design
To properly understand how this all works let's consider the following class diagram which should help.
Let's have a quick look at the design of the web application, before diving into how it all works, shall we?
Default is a standard ASP.NET wb form, and it looks like the following image in design time. This is the only page within the application.
It can be seen that this page simpy provides an upload field, and a button to submit the uploaded file.
Below that it has a literal element in which I use to show error messages (NOTE: This is not how to normally do error handling in ASP.NET, normally one would have a custom error page, but that is outside the scope of this article. This is simply to show the Exception message as quickly as possible).
Then there is a Placeholder element, which is used to add a thumbnail of the uploaded image (if sucessful).
Then there is a button to SELECT
all (using stored procedure sp_GetImages
) previously stored database images. These stored images are then bound to a DataList control. This is explained in more detail below.
That's the design of the page, but how does it all work?
So How Does It All Work
Well let's start at the beginning shall we? The following steps are carried out.
To upload and store an image
- The user selects a file from their local file system, using the upload field shown
- They then click the "Upload" button, which then checked the posted content, to see if is is actually an image. If it is valid image go to step 3, otherwise show an error message
- Create an image from the upload stream, and then convert this image to a
byte[]
array, and save this to the database using thedbAccess
class'SaveImageToDb()
method, which in turn calls thesp_AddImage
stored procedure above - If the save was successful, create a thumbnail of the image using the primary key of the current image.
To create a thumnail for an image
It is a little known fact that an image may be created as the result of writing another ASP.NET form (with no controls of its own) to the HTTP response stream. This is how we manage to do the thumbnails. Let's have a look shall we?
- If a primary key for an image is known, we can create thumbnail as shown in the following code snippet:
ThumbFromID.THUMBNAIL_SIZE = this.THUMBNAIL_SIZE;
ThumbFromID.USE_SIZE_FOR_HEIGHT = false;
imgImage = new System.Web.UI.WebControls.Image();
// set the source to the page that generates the thumbnail image
imgImage.ImageUrl = ThumbFromID.PAGE_NAME + "?" +
ThumbFromID.IMAGE_ID + "=" + img_pk;
What's actually going on here, is that we are setting two static field values within the ThumbFromID
class, which will dictate what size the thumbnail will be. Next we assign the current images ImageUrl
property the value of the string ThumbFromID.PAGE_NAME?ThumbFromID.IMAGE_ID=5;
for example. What this is doing is requesting the page ThumbFromID
to load. Remember that the page ThumbFromID
does not have any controls of its own, its sole job is to provide the correct image from the database at the requested size, on the standard HTTP response stream. This will probably make a bit more sense if we have a look at the Page_Load
event of the ThumbFromID
class.
private void Page_Load(object sender, System.EventArgs e)
{
byte[] imageData = null;
MemoryStream ms = null;
System.Drawing.Image fullsizeImage = null;
String imageID = null;
if (!Page.IsPostBack)
{
try
{
// get the ID of the image to retrieve from the database
imageID = Request.QueryString[IMAGE_ID];
imageData = dbAccess.GetImageByID(int.Parse(imageID));
// create an image from the byte array
ms = new MemoryStream(imageData);
fullsizeImage = System.Drawing.Image.FromStream(ms);
Response.ContentType = "image/Jpeg";
ImageResize ir = new ImageResize();
// Load your image and perform any resizing here
ir.File = fullsizeImage;
if (USE_SIZE_FOR_HEIGHT)
ir.Height = THUMBNAIL_SIZE;
else
ir.Width = THUMBNAIL_SIZE;
//get the thumbnail
ir.GetThumbnail().Save(Response.OutputStream,
System.Drawing.Imaging.ImageFormat.Jpeg);
}
catch (Exception ex)
{
throw new Exception(ex.Message, ex);
}
finally
{
ms.Close();
}
}
}
Can you see what is happening here? A couple of fields are created to hold the finished image and a MemoryStream
is created for temporary storage. Then the value of the images primary key is read from the request string (this would be 5 if we stick to the example above). So next the image data is fetched from the dbAccess
class by using the GetImageByID(..)
method (which in turn calls the stored procedure sp_GetImageByID
). This binary image data from the database is then placed into the MemoryStream
object. Then a new ImageRezize
object is created, and is used to create a thumbnail at the requested size. The ImageRezize
class is not my own, it is by a chap called Alex Hildyard, and is available at here
The ImageRezize
object, simply resizes the image to the correct size, and writes the image to a stream. In this case, as we are dealing with ASP.NET, and are trying to create a image control ImageUrl
property, this is set to Response.OutputStream
How about doing this with a databound control
You may want to use thumbnail images within a databound control, such as a DataList or GridView, etc. To demonstrate this let's consider the following method of the Default
page, which contains a DataList
control. As shown previously in the Design section of this article.
Well, let's look at that shall we, The Default
page provides a single button called btnSeeAll, whos job it is to SELECT all the SQL stored images by using the dbAccess
classes GetImages(..) method (which in turn calls the stored procedure sp_GetImages)
protected void dlImages_ItemDataBound(object sender, DataListItemEventArgs e)
{
System.Web.UI.WebControls.Image img = null;
// make sure this is an item in the data list (not header etc.)
if ((e.Item.ItemType == ListItemType.Item) ||
(e.Item.ItemType == ListItemType.AlternatingItem))
{
// get a reference to the image used for the bar in the row
img = (System.Web.UI.WebControls.Image)
(e.Item.FindControl("imgThumbnail"));
//get the img_pk from DataRow being bound
int img_pk = Convert.ToInt16(
((DataRowView)e.Item.DataItem).Row.ItemArray[0].ToString());
ThumbFromID.THUMBNAIL_SIZE = this.THUMBNAIL_SIZE;
ThumbFromID.USE_SIZE_FOR_HEIGHT = false;
// set the source to the page that generates the thumbnail image
img.ImageUrl = ThumbFromID.PAGE_NAME + "?" +
ThumbFromID.IMAGE_ID + "=" + img_pk;
}
}
It can be seen that this to follows the same principles as just outlined. The only difference being that the dlImages_ItemDataBound
event is raised during databinding, for each item within the databound control (A DataList in this case). As such the extraction of the primary key must be gained by examining the DataSet that is being bound to the databound control. However, once we have the current DataRowView
Primary key value, which is obtained thusly:
Convert.ToInt16(((DataRowView)e.Item.DataItem).Row.ItemArray[0].ToString())
We simpy create the thumnail the same way. This is repeated for each DataRowView
within the DataLists data source.
Full Code Listing
For those of you that want full code listings.
dbAccess
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Data.SqlClient;
using System.IO;
#region dbAccess CLASS
/// <summary>
/// Provides a wrapper around the underyling SQL database. This class
/// provides all methods that are required to INSERT / SELECT
/// images within the underyling SQL database.
/// </summary>
public sealed class dbAccess
{
/// <summary>
/// Returns a Byte[] array which represents the database stored image
/// whos primary key is the same as the img_pk input parameter
/// </summary>
/// <param name="img_pk">The primary key of the image to retrieve</param>
/// <returns>A Byte[] array which represents the database stored image
/// whos primary key is the same as the img_pk input parameter</returns>
public static byte[] GetImageByID(int img_pk)
{
//use the web.config to store the connection string, using statement
//ensure connection always closes
using (SqlConnection connection = new SqlConnection(
ConfigurationManager.ConnectionStrings[
"EasyThumbs_DB"].ConnectionString))
{
try
{
SqlCommand command = new SqlCommand("sp_GetImageByID",
connection);
command.CommandType = CommandType.StoredProcedure;
//build params
SqlParameter param0 = new SqlParameter(
"@img_pk", SqlDbType.Int);
param0.Value = img_pk;
command.Parameters.Add(param0);
//open connection, and execute stored procedure
connection.Open();
byte[] imgdata = (byte[])(command.ExecuteScalar());
connection.Close();
return imgdata;
}
catch (SqlException ex)
{
throw new Exception(ex.Message, ex);
}
}
}
/// <summary>
/// Inserts a new image using the details provided, and will then update
/// the input parameter img_pk with the correct primary key value from
/// the database, and shall also return the number of rows affected by
/// the call to this method.
/// </summary>
/// <param name="img_pk">The image primary key, the will get assigned
/// value by this method call as the parameter is passed by
/// Reference</param>
/// <param name="imgbin">A byte[] array representing the image to be
/// stored</param>
/// <returns>The number of rows affected by the call to this
/// method</returns>
public static int SaveImageToDB(ref int img_pk, byte[] imgbin)
{
try
{
//use the web.config to store the connection string, using
//statement ensure connection always closes
using (SqlConnection connection = new SqlConnection(
ConfigurationManager.ConnectionStrings[
"EasyThumbs_DB"].ConnectionString))
{
SqlCommand command = new SqlCommand("sp_AddImage",
connection);
command.CommandType = CommandType.StoredProcedure;
//build params
int IMG_PK = 0;
SqlParameter param0 = new SqlParameter("@img_pk",
SqlDbType.Int);
param0.Value = IMG_PK;
command.Parameters.Add(param0);
param0.Direction = ParameterDirection.Output;
SqlParameter param1 = new SqlParameter("@img_data",
SqlDbType.Image);
param1.Value = imgbin;
command.Parameters.Add(param1);
//open connection, and execute stored procedure
connection.Open();
int numRowsAffected = command.ExecuteNonQuery();
connection.Close();
//set the ref parameter and return value
img_pk = int.Parse(param0.Value.ToString());
//return the rows affected
return numRowsAffected;
}
}
catch (SqlException ex)
{
throw new Exception(ex.Message, ex);
}
}
/// <summary>
/// Returns a DataSet which contains all database stored images
/// </summary>
/// <returns>A DataSet which contains all database stored images
/// images</returns>
public static DataSet GetImages()
{
//use the web.config to store the connection string,
//using statement ensure connection always closes
using (SqlConnection connection = new SqlConnection(
ConfigurationManager.ConnectionStrings[
"EasyThumbs_DB"].ConnectionString))
{
try
{
SqlCommand command = new SqlCommand("sp_GetImages",
connection);
command.CommandType = CommandType.StoredProcedure;
//execute stored procedure and return DataSet
SqlDataAdapter da = new SqlDataAdapter();
da.SelectCommand = command;
DataSet ds = new DataSet();
da.Fill(ds, "IMAGES");
return ds;
}
catch (SqlException ex)
{
throw new Exception(ex.Message, ex);
}
}
}
}
#endregion
ImageResize
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Drawing;
using System.IO;
#region ImageResize CLASS
/// <summary>
/// ImageResize is a class that is based on an article that was obtained from
/// the URL http://www.devx.com/dotnet/Article/22079/0/page/3. I had to make
/// some minor changes to a couple of the properties, but otherwise it is very
/// much like the original article.
/// </summary>
public class ImageResize
{
#region Instance Fields
//instance fields
private double m_width, m_height;
private bool m_use_aspect = true;
private bool m_use_percentage = false;
private System.Drawing.Image m_src_image, m_dst_image;
private System.Drawing.Image m_image;
private ImageResize m_cache;
private Graphics m_graphics;
#endregion
#region Public properties
/// <summary>
/// gets of sets the File
/// </summary>
public System.Drawing.Image File
{
get { return m_image; }
set { m_image = value; }
}
/// <summary>
/// gets of sets the Image
/// </summary>
public System.Drawing.Image Image
{
get { return m_src_image; }
set { m_src_image = value; }
}
/// <summary>
/// gets of sets the PreserveAspectRatio
/// </summary>
public bool PreserveAspectRatio
{
get { return m_use_aspect; }
set { m_use_aspect = value; }
}
/// <summary>
/// gets of sets the UsePercentages
/// </summary>
public bool UsePercentages
{
get { return m_use_percentage; }
set { m_use_percentage = value; }
}
/// <summary>
/// gets of sets the Width
/// </summary>
public double Width
{
get { return m_width; }
set { m_width = value; }
}
/// <summary>
/// gets of sets the Height
/// </summary>
public double Height
{
get { return m_height; }
set { m_height = value; }
}
#endregion
#region Public Methods
/// <summary>
/// Returns a Image which represents a rezised Image
/// </summary>
/// <returns>A Image which represents a rezised Image, using the
/// proprerty settings provided</returns>
public virtual System.Drawing.Image GetThumbnail()
{
// Flag whether a new image is required
bool recalculate = false;
double new_width = Width;
double new_height = Height;
// Load via stream rather than Image.FromFile to release the file
// handle immediately
if (m_src_image != null)
m_src_image.Dispose();
m_src_image = m_image;
recalculate = true;
// If you opted to specify width and height as percentages of the
// original image's width and height, compute these now
if (UsePercentages)
{
if (Width != 0)
{
new_width = (double)m_src_image.Width * Width / 100;
if (PreserveAspectRatio)
{
new_height = new_width * m_src_image.Height /
(double)m_src_image.Width;
}
}
if (Height != 0)
{
new_height = (double)m_src_image.Height * Height / 100;
if (PreserveAspectRatio)
{
new_width = new_height * m_src_image.Width /
(double)m_src_image.Height;
}
}
}
else
{
// If you specified an aspect ratio and absolute width or height,
// then calculate this now; if you accidentally specified both a
// width and height, ignore the PreserveAspectRatio flag
if (PreserveAspectRatio)
{
if (Width != 0 && Height == 0)
{
new_height = (Width / (
double)m_src_image.Width) * m_src_image.Height;
}
else if (Height != 0 && Width == 0)
{
new_width = (Height / (
double)m_src_image.Height) * m_src_image.Width;
}
}
}
recalculate = true;
if (recalculate)
{
// Calculate the new image
if (m_dst_image != null)
{
m_dst_image.Dispose();
m_graphics.Dispose();
}
Bitmap bitmap = new Bitmap((int)new_width, (int)new_height,
m_src_image.PixelFormat);
m_graphics = Graphics.FromImage(bitmap);
m_graphics.SmoothingMode =
System.Drawing.Drawing2D.SmoothingMode.HighQuality;
m_graphics.InterpolationMode =
System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
m_graphics.DrawImage(
m_src_image, 0, 0, bitmap.Width, bitmap.Height);
m_dst_image = bitmap;
// Cache the image and its associated settings
m_cache = this.MemberwiseClone() as ImageResize;
}
return m_dst_image;
}
#endregion
#region Deconstructor
/// <summary>
/// Frees all held resources, such as Graphics and Image handles
/// </summary>
~ImageResize()
{
// Free resources
if (m_dst_image != null)
{
m_dst_image.Dispose();
m_graphics.Dispose();
}
if (m_src_image != null)
m_src_image.Dispose();
}
#endregion
}
#endregion
Default.aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs"
Inherits="_Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Label ID="lblInstructions" runat="server" Font-Bold="True"
Font-Names="Arial" Text="Please select an image file"></asp:Label>
<br/>
<asp:FileUpload ID="UploadFile" runat="server" Width="631px" />
<asp:Button ID="btnSubmit" runat="server" Height="20px"
OnClick="btnSubmit_Click" Text="Upload" Width="78px" />
<br/>
<br />
<asp:Label ID="lblException" runat="server" Font-Bold="True"
Font-Names="Arial" Text="ERRORS : If any exist"
ForeColor="Red"></asp:Label>
<br />
<asp:Literal ID="litException" runat="server"></asp:Literal>
<br/>
<br />
<asp:PlaceHolder id="plImage" Runat="server"></asp:PlaceHolder>
<br />
<br />
<asp:Label ID="lblSeeAll" runat="server" Font-Bold="True"
Font-Names="Arial"
Text="View all saved images from SQL database"></asp:Label>
<br />
<br />
<asp:Button ID="btnSeeAll" runat="server" Height="20px"
Text="See All Images" Width="115px" OnClick="btnSeeAll_Click" />
<br />
<br />
<asp:datalist id="dlImages" Runat="server" Width="90%"
ItemStyle-HorizontalAlign="Left" RepeatLayout="Table"
RepeatDirection="Horizontal" RepeatColumns="4"
OnItemDataBound="dlImages_ItemDataBound">
<ItemTemplate>
<asp:Image id="imgThumbnail" runat="server" borderSize="5" />
</ItemTemplate>
</asp:datalist>
<br/>
</div>
</form>
</body>
</html>
Default.aspx.cs
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.IO;
public partial class _Default : System.Web.UI.Page
{
#region instance fields
//instance fields
protected System.Web.UI.WebControls.Image imgImage;
private int THUMBNAIL_SIZE = 60;
#endregion
protected void Page_Load(object sender, EventArgs e)
{
}
/// <summary>
/// Creates an image, by querying the SQL database with the given img_pk
/// parameter. The query will return a byte[] array, which represents the
/// image. This byte[] array is then converted into an image and added to
/// the placeholder control "plImage" which is on this page
/// </summary>
/// <param name="img_pk">The primary key to fetch the image data for</param>
private void createImageFromDBBytes(int img_pk)
{
ThumbFromID.THUMBNAIL_SIZE = this.THUMBNAIL_SIZE;
ThumbFromID.USE_SIZE_FOR_HEIGHT = false;
imgImage = new System.Web.UI.WebControls.Image();
// set the source to the page that generates the thumbnail image
imgImage.ImageUrl = ThumbFromID.PAGE_NAME + "?" +
ThumbFromID.IMAGE_ID + "=" + img_pk;
litException.Visible = false;
plImage.Controls.Clear();
plImage.Controls.Add(imgImage);
}
/// <summary>
/// returns a byte[] array which represents the input Image
/// </summary>
/// <param name="bmp">The source image to return as byte[] array</param>
/// <returns>byte[] array which represents the input Image</returns>
private byte[] BmpToBytes(System.Drawing.Image bmp)
{
MemoryStream ms = null;
byte[] bmpBytes = null;
try
{
ms = new MemoryStream();
// Save to memory using the Jpeg format
bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
// read to end
bmpBytes = ms.GetBuffer();
}
catch (Exception ex)
{
return null;
}
finally
{
bmp.Dispose();
if (ms != null)
{
ms.Close();
}
}
return bmpBytes;
}
/// <summary>
/// Will attempt ot save the posted file contents to SQL server
/// table. Will firstly check that the posted file is an image
/// </summary>
/// <param name="sender">the btnSubmit</param>
/// <param name="e">the btnSubmit EventArgs</param>
protected void btnSubmit_Click(object sender, EventArgs e)
{
try
{
string imgContentType = UploadFile.PostedFile.ContentType;
//check if an image
if (imgContentType.ToLower().StartsWith("image"))
{
//get the image from upload stream
System.Drawing.Bitmap b = (
System.Drawing.Bitmap)System.Drawing.Image.FromStream(
UploadFile.PostedFile.InputStream);
//get pk, to allow image to be created on this page from the
//SQL server stores byte[] array
int img_pk = 0;
//store the image in database, and also ccheck to see if it
//was successful, and if so create
//a thumnail here of the stored image
int RowsAffected = dbAccess.SaveImageToDB(ref img_pk,
BmpToBytes(b));
if (RowsAffected > 0)
{
createImageFromDBBytes(img_pk);
}
else
{
litException.Text = ("<br><p>ERROR saving image </p>");
}
}
else
{
litException.Text = ("<br><p>The file is not an image</p>");
}
}
catch (Exception ex)
{
litException.Text = ("<br><p>" + ex.Message + "</p>");
}
}
/// <summary>
/// Will attempt fetch all SQL server stored images, and will bind the
/// resultant DataSet to the "dlImages" datalist on this page. When the
/// databinding occurs the dlImages_ItemDataBound(..) event is fired. At
/// that stage the image control is found, and a new thumbnail is
/// constructed for each DataSet row value
/// </summary>
/// <param name="sender">the btnSeeAll</param>
/// <param name="e">the btnSeeAll EventArgs</param>
protected void btnSeeAll_Click(object sender, EventArgs e)
{
try
{
// set the source of the data for the repeater control and bind it
DataSet dsImgs = dbAccess.GetImages();
dlImages.DataSource = dsImgs;
dlImages.DataBind();
}
catch (Exception ex)
{
litException.Text = ("<br><p>" + ex.Message + "</p>");
}
}
/// <summary>
/// Occurs when the server side DataList starts databinding. This event
/// is used to intercept the databinding to create a new Image that
/// uses the binary array value of the data within the DataList datasource
/// </summary>
/// <param name="sender">the datalist</param>
/// <param name="e">the datalist DataListItemEventArgs</param>
protected void dlImages_ItemDataBound(object sender,
DataListItemEventArgs e)
{
System.Web.UI.WebControls.Image img = null;
// make sure this is an item in the data list (not header etc.)
if ((e.Item.ItemType == ListItemType.Item) ||
(e.Item.ItemType == ListItemType.AlternatingItem))
{
// get a reference to the image used for the bar in the row
img = (System.Web.UI.WebControls.Image)
(e.Item.FindControl("imgThumbnail"));
//get the img_pk from DataRow being bound
int img_pk = Convert.ToInt16(
((DataRowView)e.Item.DataItem).Row.ItemArray[0].ToString());
ThumbFromID.THUMBNAIL_SIZE = this.THUMBNAIL_SIZE;
ThumbFromID.USE_SIZE_FOR_HEIGHT = false;
// set the source to the page that generates the thumbnail image
img.ImageUrl = ThumbFromID.PAGE_NAME + "?" +
ThumbFromID.IMAGE_ID + "=" + img_pk;
}
}
}
ThumbFromID.aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="ThumbFromID.aspx.cs"
Inherits="ThumbFromID" %>
ThumbFromID.aspx.cs
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Data.OleDb;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
#region ThumbFromID CLASS
/// <summary>
/// ThumbFromID inherits from <see System.Web.UI.Page>System.Web.UI.Page</see>
/// Retrieves a binary array from the SQL Server database by the use of the
/// <see dbAccess>dbAccess</see>class. Once this binary
/// array is retrieved from the database, it is written to a memory stream
/// which is then written to the standard Html Response stream, this
/// binary data represents an image from the database, which has been scaled
/// using the fields within this class
/// </summary>
public partial class ThumbFromID : System.Web.UI.Page
{
#region Instance Fields
// constants used to create URLs to this page
public const String PAGE_NAME = "ThumbFromID.aspx";
//the image primary key for use when getting image data from database
public const String IMAGE_ID = "img_pk";
// height of the thumbnail created from the original image
public static int THUMBNAIL_SIZE;
// true if using thumbnail THUMBNAIL_SIZE for height, else it is used
// for width
public static bool USE_SIZE_FOR_HEIGHT;
#endregion
#region Private Methods
/// <summary>
/// Retrieves a binary array from the SQL Server database by the use
/// of the <see dbAccess>dbAccess</see>class. Once this binary
/// array is retrtieved from the database, it is written to a memory
/// stream which is then written to the standard Html Response stream,
/// this binary data represents an image from the database, which has
/// been scaled using the fields within this class
/// </summary>
private void Page_Load(object sender, System.EventArgs e)
{
byte[] imageData = null;
MemoryStream ms = null;
System.Drawing.Image fullsizeImage = null;
String imageID = null;
if (!Page.IsPostBack)
{
try
{
// get the ID of the image to retrieve from the database
imageID = Request.QueryString[IMAGE_ID];
imageData = dbAccess.GetImageByID(int.Parse(imageID));
// create an image from the byte array
ms = new MemoryStream(imageData);
fullsizeImage = System.Drawing.Image.FromStream(ms);
Response.ContentType = "image/Jpeg";
ImageResize ir = new ImageResize();
// Load your image and perform any resizing here
ir.File = fullsizeImage;
if (USE_SIZE_FOR_HEIGHT)
ir.Height = THUMBNAIL_SIZE;
else
ir.Width = THUMBNAIL_SIZE;
//get the thumbnail
ir.GetThumbnail().Save(Response.OutputStream,
System.Drawing.Imaging.ImageFormat.Jpeg);
}
catch (Exception ex)
{
throw new Exception(ex.Message, ex);
}
finally
{
ms.Close();
}
}
}
#endregion
#region Web Form Designer generated code
/// <summary>
/// privided automaitically by Web Form Designer
/// </summary>
/// <param name="e">the event args</param>
override protected void OnInit(EventArgs e)
{
//
// CODEGEN: This call is required by the ASP.NET Web Form Designer.
//
InitializeComponent();
base.OnInit(e);
}
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.Load += new System.EventHandler(this.Page_Load);
}
#endregion
}
#endregion
Web.Config
<?xml version="1.0"?>
<!--
Note: As an alternative to hand editing this file you can use the
web admin tool to configure settings for your application. Use
the Website->Asp.Net Configuration option in Visual Studio.
A full list of settings and comments can be found in
machine.config.comments usually located in
\Windows\Microsoft.Net\Framework\v2.x\Config
-->
<configuration>
<appSettings/>
<connectionStrings>
<add name="EasyThumbs_DB"
connectionString="server=localhost;uid=sa;pwd=sa;Database=EasyThumbs"/>
</connectionStrings>
<system.web>
<!--
Set compilation debug="true" to insert debugging
symbols into the compiled page. Because this
affects performance, set this value to true only
during development.
-->
<compilation debug="true"/>
<!--
The <authentication> section enables configuration
of the security authentication mode used by
ASP.NET to identify an incoming user.
-->
<authentication mode="Windows"/>
<!--
The <customErrors> section enables configuration
of what to do if/when an unhandled error occurs
during the execution of a request. Specifically,
it enables developers to configure html error pages
to be displayed in place of a error stack trace.
<customErrors mode="RemoteOnly"
defaultRedirect="GenericErrorPage.htm">
<error statusCode="403" redirect="NoAccess.htm" />
<error statusCode="404" redirect="FileNotFound.htm" />
</customErrors>
-->
</system.web>
</configuration>
What Do You Think ?
That's it, I would just like to ask, if you liked the article please vote for it.
Conclusion
I hope this has not been to hard for most folks to follow. I think its a fairly easy thumbnail solution.
History
v1.0 06/01/07