ASP.NET C# Get retrieve and show image from SQL Server database - c#

I want to retrieve an image from a SQL Server database and show in a Image tool.
I have this code
<asp:Image ID="Image1" runat="server" CssClass="style2" Height="166px" Width="488px" />
SqlConnection connect = null;
string connectstring = "Data Source=.\\SQLEXPRESS;Initial Catalog=teste;Integrated Security=true;pooling=false";
connect = new SqlConnection(connectstring);
connect.Open();
string Scmd = "SELECT id, imagem where id = 2";
SqlCommand cmd = new SqlCommand(Scmd, connect);
SqlDataReader reader = cmd.ExecuteReader();
reader.Read();
if (reader.HasRows)
{
Label1.Text = reader[0].ToString();
byte[] imagem = (byte[])(reader[1]);
MemoryStream ms = new MemoryStream(imagem);
Image1.ImageUrl = ms.FromStream(ms); //i tried this
}
But I can't do this:
Image1.ImageUrl = ms.FromStream(ms);
because I get an error.
Somebody please can help me? The only problem I have is show the image.
Please help, thanks.

You can generate base64string out of byte array and use that as inline image source.
Convert to base64string. Refer this.
byte[] imagem = (byte[])(reader[1]);
string base64String = Convert.ToBase64String(imagem) ;
Use this string as inline image like following. Refer this.
Image1.ImageUrl = String.Format("data:image/jpg;base64,{0}",base64String);
Assumption: image saved as jpg.
If this differs, then change line in step#2.
Disclaimer: Base64string as image is suitable for small sized image , but if we have bigger image, then the string produced will have large sized string. Advantage is , browser don't have to request multiple times for each image ( if you implemented this as image.src= "http://handler-to-image").

Related

Saving and retrieving of images from SQL Server database using c#

I have created a web page where I have used Image control to display the image. Along with this control I have some labels and input box also
Below is the code which I have used to save the image to database
byte[] imageSize = new byte[FileUpload1.PostedFile.ContentLength];
HttpPostedFile uploadedImage = FileUpload1.PostedFile;
uploadedImage.InputStream.Read(imageSize, 0, (int)FileUpload1.PostedFile.ContentLength);
SqlParameter UploadedImage = new SqlParameter("#image", SqlDbType.Image, imageSize.Length);
UploadedImage.Value = imageSize;
string sql = "insert into imageDB(Image) values (#image)";
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.Add(UploadedImage);
cmd.ExecuteNonQuery();
}
and below is the code I have used to retrieve the image from database
byte[] rawImg = (byte[])rdr["image"];
MemoryStream Stream = new MemoryStream();
Stream.Write(rawImg, 0, rawImg.Length);
Bitmap Display_Picture = new Bitmap(Stream);
//after this no idea how to proceed
I have read some links all are suggesting we can not set this byte information to Image control.
Let me know if my way of retrieving the image from data base is right, if its right, what type of control I should use, so that image which has been retrieved from database can be displayed on web page
Is my way of retrieving the image from database right?
I would use the following code instead (sorry not tested):
byte[] imageBytes = Convert.FromBase64String(rdr["image"]);
MemoryStream stream = new MemoryStream(imageBytes);
Image image = Image.FromStream(stream);
How do I bind the image to an asp.net image control?
I would create an HttpHandler which gets and returns the image. Then bind the ImageUrl property on the asp:Image to the url of the HttpHandler.
How you can do this you can see in the answer of Dale Ragan over here: How to bind a MemoryStream to asp:image control?
First, in your example your have to reset the Position inside your stream to 0: Stream.Position = 0;
Second, you have to write your image to a local cache folder of your web service that is part of your web application. You image control can have a Source-reference (img.src) to the address of that image.
Or... you can create an AXD-file / HttpHandler. An AXD file is a file, just like an ASPX, but specialized in returning any type of data, like an image.
For more info, see: http://blog.kurtschindler.net/post/using-httphandlers-to-serve-image-files
To retrieve image, and show on asp.net Image control, you can
cn.Open();
SqlCommand cm = new SqlCommand("select * from ImageCollection where img_id='" + DropDownList1.SelectedItem.ToString() + "'", cn);
SqlDataAdapter da = new SqlDataAdapter(cm);
SqlDataReader dr = cm.ExecuteReader();
try
{
if (dr.Read())
{
string image1 = Convert.ToString(DateTime.Now.ToFileTime());
FileStream fs1 = new FileStream(image1, FileMode.CreateNew, FileAccess.Write);
byte[] bimage1 = (byte[])dr["passport_photo"];
fs1.Write(bimage1, 0, bimage1.Length - 1);
fs1.Flush();
Image1.ImageUrl = "~/images/"+DropDownList1.SelectedItem.ToString();
}
dr.Close();
cn.Close();
}
catch (Exception ex)
{
throw ex;
}
Alternative solution:
Implement a handler to serve the image. Have a look at the System.Web.IHttpHandler interface.
The idea would be to write an image tag in your page along the lines of:
<asp:image runat="server" imageurl="~/Image.ashx?ID=xxx" />
Then in your handler implementation, get the id from the querystring, retrieve the image as you're already doing and then write directly to the response stream.

how to delete image which is stored as varbinary format in database

I have a PictureBox with an image and a delete button. The image is stored in a varbinary(MAX) format in the database. How do I delete it when the delete button is pressed?
I'm using this code to save an image into the database:
byte[] data;
using (System.IO.MemoryStream stream = new System.IO.MemoryStream())
{
conn.Open();
Image img = pictureBox1.Image;
img.Save(stream, System.Drawing.Imaging.ImageFormat.Jpeg);
data = stream.ToArray();
cmd.CommandText = "insert into images values(#images)";
cmd.Parameters.AddWithValue("#images", data);
int res = cmd.ExecuteNonQuery();
MessageBox.Show("success");
}
I don't see why the following wouldn't work.
cmd.CommandText = "delete from images where ID = x";
Sending plain SQL like this is getting fairly outdated and can be down right dangerous when implemented with a UI improperly, you should strongly consider using LINQ
http://en.wikipedia.org/wiki/Language_Integrated_Query

Issues using OleDbConnection to export an image in an excel document in c#

I want to export an image to an excel document in c#
The image the following formats:
System.Windows.Media.Imaging.BitmapImage
These are the connection details:
private const string OleDbConnection = "provider=Microsoft.Jet.OLEDB.4.0;Data Source='{0}';Extended Properties=Excel 8.0;";
private const string OleDbInsert = "INSERT INTO [Report] ([Time], [Elapsed], [Description], [Picture]) values( #timestamp, #elapsed, #description, #pic);";
private const string OleDbCreate = "CREATE TABLE [Report] ([Time] varchar(255), [Elapsed] varchar(255), [Description] varchar(255), [pic] blob);";
I am using the following code to write the image in excel:
foreach (var e in Entries)
{
using(var command = new OleDbCommand { Connection = connection, CommandText = OleDbInsert })
{
command.Parameters.Add(new OleDbParameter("#component", OleDbType.BSTR) { Value = e.val1 });
command.Parameters.Add(new OleDbParameter("#result", OleDbType.BSTR) { Value = e.val2 });
command.Parameters.Add(new OleDbParameter("#description", OleDbType.BSTR) { Value = e.val3});
if (e.EncodedScreenshot != string.Empty)
{
byte[] imageContent = imageToByteArray(ImageWpfToGDI(e.Picture));
OleDbParameter ph = new OleDbParameter("#pic", OleDbType.Binary) { Value = imageContent};
ph.Size = imageContent.Length;
command.Parameters.Add(ph);
}
}
These are the methods I am using:
public byte[] imageToByteArray(Image imageIn)
{
MemoryStream ms = new MemoryStream();
imageIn.Save(ms, System.Drawing.Imaging.ImageFormat.Gif);
return ms.ToArray();
}
private System.Drawing.Image ImageWpfToGDI(System.Windows.Media.Imaging.BitmapImage image)
{
MemoryStream ms = new MemoryStream();
var encoder = new System.Windows.Media.Imaging.BmpBitmapEncoder();
encoder.Frames.Add(System.Windows.Media.Imaging.BitmapFrame.Create(image as System.Windows.Media.Imaging.BitmapSource));
encoder.Save(ms);
ms.Flush();
return System.Drawing.Image.FromStream(ms);
}
All the data exports to the Excel file except the image (and there definitely exists an image). Could you please give me some advice on how to fix this? I have been searching online alot but I still cannot find a solution.
I made some modifications according to this link: Insert and retrieve Image in Access 2007 DB from C# App. I believe my error is because of the image datatypes. What datatype should I use for the image in the DB and OleDbParameter?
Could someone help me out please? I would be grateful with any response.
Many thanks! :)
Just incase someone stumbles across the same problem..
I could not find a way to export images to an excel file using OleDbParameter. If anyone knows how to do this then please correct me.
Instead I used this approach: http://csharp.net-informations.com/excel/csharp-insert-picture-excel.htm
With this help: How to insert a picture in to Excel from C# app?
And it works perfectly well.

Saveable image library with compression?

this may be impossible, or rather, not very popular, but I was wondering how I'd go about creating a data file for images, that would actually compress them? Say I had 200MB total of image files, is there some system I can use to store them in a single file, that would compress them to a total size of like 150MB? (Just example numbers, ratios not important).
I know I can encode the images with Base64 and then store them in an SQLite database, but I read that storing images in their encoded forms actually resulted in a slightly larger size than the original image file itself.
I was also thinking of a ZIP file, but I wasn't sure if it could be used as a 'library' as such?
If something like this doesn't exist as a predefined class, could someone lead me on the right track?
This is a mock of what I'm sort of looking for:
class ImageLibrary {
//this is where the code would go for the library?
}
class MyProgram{
public MyProgram()
{
ImageLibrary library = new ImageLibrary();
library.Add(<Image object here, with an ID of sorts>);
library.Add(<Another image object here, also with an ID>);
Load += new FormLoadEventHandler(MyProgram_Load);
}
void MyProgram_Load(object sender, EventArgs e)
{
PictureBox.Image = library.Get(<image id here>);
}
}
I hope this is possible. Else, I'll just put up with a slightly larger file size and Base64 encode them. But, because I have, at the moment, almost 500 images I want to store, a kB saved is a kB earned. :) Also, please don't judge the quality of my code example, it's just a mock up and I wrote it off the cuff.
Cheers, and thankyou in advance.
If save your images as binary files will help this is a code I use to convert them to binary and then save into SQLite:
public byte[] ImageToByte(Image image, System.Drawing.Imaging.ImageFormat format){
using (MemoryStream ms = new MemoryStream())
{
// Convert Image to byte[]
image.Save(ms, format);
byte[] imageBytes = ms.ToArray();
return imageBytes;
}
}
public Image ByteToImage(byte[] imageBytes)
{
// Convert byte[] to Image
MemoryStream ms = new MemoryStream(imageBytes, 0, imageBytes.Length);
ms.Write(imageBytes, 0, imageBytes.Length);
Image image = new Bitmap(ms);
return image;
}
And then to save the binary:
void SaveImage(byte[] image){
string conStringDatosUsuarios = #" Data Source = \Program Files\GPS___CAM\Data\DatosUsuarios.s3db ";
SQLiteConnection con = new SQLiteConnection(conStringDatosUsuarios);
SQLiteCommand cmd = con.CreateCommand();
cmd.CommandText = String.Format("INSERT INTO Users (Foto) VALUES (#0);");
SQLiteParameter p = new SQLiteParameter("#0", System.Data.DbType.Binary);
p.Value = image;
cmd.Parameters.Add(p);
con.Open();
try
{
cmd.ExecuteNonQuery();
}
catch (Exception exc1)
{
MessageBox.Show(exc1.Message);
}
con.Close();
}
Hope it helps
EDIT As you asked, I'm updating with the load image code:
(to convert the byte to image you must use the ByteToImage function)
void LoadImage(string tag){
string query = "SELECT Foto FROM Users;";
string conString = #" conection to your database ";
SQLiteConnection con = new SQLiteConnection(conString);
SQLiteCommand cmd = new SQLiteCommand(query, con);
con.Open();
try
{
SQLiteDataReader rdr = cmd.ExecuteReader();
try
{
while (rdr.Read())
{
pictureBox1.Image = ByteToImage((System.Byte[])rdr[0]);
}
}
catch (Exception exc) { MessageBox.Show(exc.Message); }
}
catch (Exception ex) { MessageBox.Show(ex.Message); }
con.Close();
}
EDIT 2 Try this to see which type of data are you trying to load:
System.Type checkType = rdr[0].GetType();
pictureBox1.Image = ByteToImage((System.Byte[])rdr[0]);
add the first line in your code and put a breakpoint in that line. Check checkType's type. Probably it isn't binary. Let me know the result to help you.
Check out this article: http://msdn.microsoft.com/en-us/library/aa479502.aspx
I hope it helps. An idea for accessing files from a ZIP. It's not ready-to-use solution, but a nice concept explanation.

Read a picture from Access DB into PictureBox

I have been trying to read a picture saved in Access DB as a OLE object in a PictureBox in a C# windows Application.
The code that does this is presented below:
string connString = #"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=D:\Rajesh\SampleDB_2003.mdb;";
OleDbConnection oConn = new OleDbConnection(connString);
oConn.Open();
string commandString = "select * from employee where id = " + id + "";
OleDbCommand oCmd = new OleDbCommand(commandString, oConn);
OleDbDataReader oReader = oCmd.ExecuteReader(CommandBehavior.SequentialAccess);
while (oReader.Read())
{
txtID.Text = ((int)oReader.GetValue(0)).ToString();
txtName.Text = (string)oReader.GetValue(1);
txtAge.Text = ((int)oReader.GetValue(2)).ToString();
txtType.Text = (string)oReader.GetValue(3);
byte[] imageBytes = (byte[])oReader.GetValue(4);
MemoryStream ms = new MemoryStream();
ms.Write(imageBytes, 0, imageBytes.Length);
Bitmap bmp = new Bitmap(ms);
pbPassport.Image = bmp;
}
When I execute the above code, an 'Parameter is not valid' exception is thrown at the line:
Bitmap bmp = new Bitmap(ms)
From the exception message, it is clear that 'ms' is in a format that is not recognisable. Any suggestion to get past this?
Unfortunately I have no good answer for you, but I can tell you that when I tried, I got the same results. Sometimes skipping the first 78 bytes of the byte array worked, sometimes it didn't.
This is because the OLE Object datatype stores some kind of header in the field, so that Access knows what type of OLE Object it is. I could not find a reliable way to work out exactly where this header stopped and real data started, but I also gave up, so good luck :)
Do a google search for AccessHdr. You'll find references to AccessHdr.cpp and AccessHdr.h. These will illustrate what is need to extract the streams without the header.
You can't read OLE objects so easily. In fact, it is bad practice to keep pictures as OLE objects in database.
It is preferred to have em as BLOB objects or path and filename at some storage. AccessImagine can handle both scenarios for MS Access and C#. You can download it here - http://access.bukrek.net
You can try:
pbPassport.Image = Image.FromStream(ms);
Your bytestream is corrupted somehow, becouse I tried the exact method of yours but filled the byte array with PNG data from a file instead.
I would suggest creating two streams, one from the database, and one from the file that was the source of the image in the database. Then compare them byte by byte. If there is even one byte of diffrence, the database image data is corrupt.

Categories