Introduction
This article shows you how to upload an image in a C# application, save it in a database and display it in another aspx page.
Background
HTML img
tag and Image control in C# always look for an image on the hard disk or some physical location on a server. This article shows how to overcome that by specifying the image source as another aspx file which returns an image.
It may not be feasible to store all the images on the hard disk and index them. It also takes more time to read and write to a hard disk. So, storing the images in database is the way to go if your application uses more images in a dynamic page.
This article shows how to display dynamic images from database, how to convert image to bytearray and how to use generic handlers.
Using the Code
First the uploaded image must be saved in the database.
Image Upload
Upload functionality can be implemented easily by using the Fileupload
control and a submit button in the upload page.
<asp:FileUpload runat="server" ID="flImage" />
<asp:Button runat="server" ValidationGroup="Details" ID="btnSubmit" Text="Upload"
onclick="btnSubmit_Click" />
The selected image from the fileupload
control must be stored in the msg
table. Let us assume the msg
table has two fields:
Table Name: msg
Field Name |
Data Type |
Primary Key |
Nullable |
msgid |
int |
Yes |
No |
pic1 |
blob |
No |
Yes |
Have the msgid
as an autoincrement field if required so that it may not be required to be updated.
On the submit button click event, insert a record in msg
table.
The selected image must be converted to a byte
array before being inserted into the table.
private byte[] ConvertImageToByteArray(System.Drawing.Image imageToConvert,
System.Drawing.Imaging.ImageFormat formatOfImage)
{
byte[] Ret;
try
{
using (MemoryStream ms = new MemoryStream())
{
imageToConvert.Save(ms, formatOfImage);
Ret = ms.ToArray();
}
}
catch (Exception) { throw; }
return Ret;
}
On the submit button click event, get the selected image in the Image
object by calling...
System.Drawing.Image.FromStream(flImage.PostedFile.InputStream)
... and store it in the image
object. This image
object must be converted to a byte
array to be able to store in a blob
field. This is done by calling the above ConvertImageToByteArray()
function.
Now setup the database connection in the button click event and update the msg
table's pic1
field with the bytearray
that we got from the ConvertImageToByteArray()
function.
protected void btnSubmit_Click(object sender, EventArgs e)
{
System.Drawing.Image imag = System.Drawing.Image.FromStream(
flImage.PostedFile.InputStream);
System.Data.SqlClient.SqlConnection conn = null;
try
{
try
{
conn = new System.Data.SqlClient.SqlConnection(
ConfigurationManager.ConnectionStrings["ConnStr"].ConnectionString);
conn.Open();
System.Data.SqlClient.SqlCommand insertCommand =
new System.Data.SqlClient.SqlCommand(
"Insert into [msg] (msgid, pic1) Values (1, @Pic)", conn);
insertCommand.Parameters.Add("Pic", SqlDbType.Image, 0).Value =
ConvertImageToByteArray(imag, System.Drawing.Imaging.ImageFormat.Jpeg);
int queryResult = insertCommand.ExecuteNonQuery();
if (queryResult == 1)
lblRes.Text = "msg record Created Successfully";
}
catch (Exception ex)
{
lblRes.Text = "Error: " + ex.Message;
}
}
finally
{
if (conn != null)
conn.Close();
}
}
Generic Handler to Display Image
As we know, the aspx image control looks for a physical location of an Image file in its ImageUrl
attribute. The trick is to specify another dedicated handler file which will act as an image. This handler (ImgHandler.ashx) will not have any HTML decoration since we are not displaying this page separately, instead it will act as an image. To do that, its ProcessRequest
event must be modified to read the image from the database and return the image as the response.
Calling Response.BinaryWrite()
function from the ProcessRequest
event will make this ashx handler as an image by the calling aspx page.
public void ProcessRequest (HttpContext context)
{
System.Data.SqlClient.SqlDataReader rdr = null;
System.Data.SqlClient.SqlConnection conn = null;
System.Data.SqlClient.SqlCommand selcmd = null;
try
{
conn = new System.Data.SqlClient.SqlConnection
(System.Configuration.ConfigurationManager.ConnectionStrings
["ConnectionString"].ConnectionString);
selcmd = new System.Data.SqlClient.SqlCommand
("select pic1 from msg where msgid=" +
context.Request.QueryString["imgid"], conn);
conn.Open();
rdr = selcmd.ExecuteReader();
while (rdr.Read())
{
context.Response.ContentType = "image/jpg";
context.Response.BinaryWrite((byte[])rdr["pic1"]);
}
if (rdr != null)
rdr.Close();
}
finally
{
if (conn != null)
conn.Close();
}
}
In the above code, notice that the ProcessRequest
event opens the database and loads the image with the image id matching the image id sent from the request query string.
This code only saves and retrieves images in JPG format. Although other image formats like GIF, PNG, BMP, etc. will work with the same code, the image quality will not be maintained if all other image formats are read as JPG formats. This code must be updated to handle different image formats while writing to database and setting the content type in the response.
Display the Image
Now this can be accessed from any aspx page by setting the ImageUrl
to the above handler.
<asp:Image ID="picone" ImageUrl="ImgHandler.ashx?imgid=1" runat="server" />
imgid
is sent as a querystring to ImgHandler.ashx in order to fetch the right image from the database and display it.
Points of Interest
Image control in C# expects ImageUrl
which is a physical image in the server. This article shows the workaround of making an ashx handler behave like a physical image. It also presents all the related code behind saving and retrieving image to and from database. This article shows database access in plain SQL in code for quick understanding. These SQL statements must be protected to prevent from SQL injection by hackers.
Happy coding!
History
- 13th February, 2009: Initial post