Retrieve image from SQL Server using ASP.NET web service - c#

I have a SQL Server (2008 R2) with an Image table, the table has a column with type image. I insert my Image into this column using
Stream fs = FileUpload1.PostedFile.InputStream;
BinaryReader br = new BinaryReader(fs);
Byte[] bytes = br.ReadBytes((Int32)fs.Length);
//insert the file into database
string strQuery = "insert into pm005.images(imageName, type, alt, img)" + " values (#Name, #ContentType, #Alt, #Data)";
SqlCommand cmd = new SqlCommand(strQuery);
cmd.Parameters.Add("#Name", SqlDbType.VarChar).Value = filename;
cmd.Parameters.Add("#ContentType", SqlDbType.VarChar).Value = contenttype;
cmd.Parameters.Add("#Alt", SqlDbType.VarChar).Value = TextBox1.Text;
cmd.Parameters.Add("#Data", SqlDbType.Binary).Value = bytes;
InsertUpdateData(cmd);
lblMessage.ForeColor = System.Drawing.Color.Green;
lblMessage.Text = "File Uploaded Successfully";
private Boolean InsertUpdateData(SqlCommand cmd)
{
// Open a connection the the SQL Server
SqlConnection con = new SqlConnection();
con.ConnectionString = "server=sql-server;integrated security=SSPI;database=pm005";
cmd.CommandType = CommandType.Text;
cmd.Connection = con;
try
{
con.Open();
cmd.ExecuteNonQuery();
return true;
}
catch (Exception ex)
{
Response.Write(ex.Message);
return false;
}
finally
{
con.Close();
con.Dispose();
}
}
This i believe works fine, because the insert returns true, and i can see the data in the database.
However i cant for the life of me see how i'm supposed to get this image back out. Specifically what i want is to be able to call my web service, pass it the imageID and have the image (and only the image) returned to me. Much like its done with PHP. THis is the code im using now.
[WebMethod]
[ScriptMethod(UseHttpGet = true)]
public System.Drawing.Image getImage(int imageID, string uName, string pword)
{
string str="";
try
{
SqlCommand cmd = getSQLCommand("SELECT img FROM pm005.images WHERE id="+imageID);
byte[] Img = (byte[])cmd.ExecuteScalar();
// Convert the image record to file stream and display it to picture control
str = Convert.ToString(DateTime.Now.ToFileTime());
FileStream fs = new FileStream(str, FileMode.CreateNew, FileAccess.Write);
fs.Write(Img, 0, Img.Length);
fs.Flush();
fs.Close();
}
catch
{
}
finally
{
}
System.Drawing.Image theImage = System.Drawing.Image.FromFile(str);
return theImage;
}
Which gives the error:
System.ArgumentException: The path is not of a legal form.
at System.IO.Path.NormalizePath(String path, Boolean fullCheck, Int32 maxPathLength)
at System.IO.Path.GetFullPathInternal(String path)
at System.IO.Path.GetFullPath(String path)
at System.Drawing.IntSecurity.UnsafeGetFullPath(String fileName)
at System.Drawing.IntSecurity.DemandReadFileIO(String fileName)
at System.Drawing.Image.FromFile(String filename, Boolean useEmbeddedColorManagement)
at WebService2.Service1.getImage(Int32 imageID, String uName, String pword)
I've looked at so many tutorials, and not find any solid answer except "use PHP". If i have to i will, but surely there must be a way to do it in ASP.NET?

Try specifying the Full FilePath:
FileStream fs = new FileStream(#"C:\Temp\YourFile.jpg", FileMode.CreateNew, FileAccess.Write);
Edit:
Rather than using the File System it sounds like you want to do it in memory:
public byte[] imageToByteArray(System.Drawing.Image imageIn)
{
MemoryStream ms = new MemoryStream();
imageIn.Save(ms,System.Drawing.Imaging.ImageFormat.Gif);
return ms.ToArray();
}
public Image byteArrayToImage(byte[] byteArrayIn)
{
MemoryStream ms = new MemoryStream(byteArrayIn);
Image returnImage = Image.FromStream(ms);
return returnImage;
}
...
System.Drawing.Image theImage = null;
try
{
SqlCommand cmd = getSQLCommand("SELECT img FROM pm005.images WHERE id="+imageID);
byte[] Img = (byte[])cmd.ExecuteScalar();
theImage = byteArrayToImage(Img);
}
catch
{
}
finally
{
}
return theImage;
}

Related

how to load a default image from .ashx when SQL BLOB is unavailable

I am new to ASP & C# and have been unable to figure out how to do this.
I am loading BLOB's from a bd via an .ashx file like so <img src="getimage.ashx" /> and it works fine, but sometimes there is no BLOB or it is empty.
here is the basic code
SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["DataSource.iMIS.Connection"].ConnectionString);
SqlCommand cmd = new SqlCommand("SELECT PICTURE_LOGO FROM Name_Picture WHERE ID = #EmpID", con);
cmd.CommandType = CommandType.Text;
cmd.Parameters.Add("#EmpID", id);
con.Open();
byte[] pict = (byte[])cmd.ExecuteScalar();
con.Close();
ctx.Response.ContentType = "image/bmp";
ctx.Response.OutputStream.Write(pict, 0, pict.Length);
My thought is to check pict.Length right after con.Close() and if it fails, I want to display a default image, or even text.
Is that possible? How?
If you want to load an image from the disk when none is found in the DB, use this snippet.
public void ProcessRequest(HttpContext context)
{
//create a new byte array
byte[] pict = new byte[0];
//create a connection to the db and a command
using (SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["DataSource.iMIS.Connection"].ConnectionString))
using (SqlCommand command = new SqlCommand("SELECT PICTURE_LOGO FROM Name_Picture WHERE ID = #EmpID", connection))
{
//set the proper command type
command.CommandType = CommandType.Text;
//replace the parameters
command.Parameters.Add("#EmpID", SqlDbType.Int).Value = id;
try
{
//open the db and execute the sql string
connection.Open();
pict = (byte[])command.ExecuteScalar();
}
catch (Exception ex)
{
//catch any errors like unable to open db or errors in command. view with ex.Message
}
}
//if no image found in database load the default from disk
if (pict == null || pict.Length == 0)
{
pict = File.ReadAllBytes(context.Server.MapPath("/noimage.bmp"));
}
//clear the buffer stream
context.Response.ClearHeaders();
context.Response.Clear();
context.Response.Buffer = true;
//set the correct ContentType
context.Response.ContentType = "image/bmp";
//set the filename for the image
context.Response.AddHeader("Content-Disposition", "attachment; filename=\"ImageName.bmp\"");
//set the correct length of the string being send
context.Response.AddHeader("content-Length", pict.Length.ToString());
//send the byte array to the browser
context.Response.OutputStream.Write(pict, 0, pict.Length);
//cleanup
context.Response.Flush();
context.ApplicationInstance.CompleteRequest();
}
After a lot more searching and a lot of 'HttpCompileException(s)' I got this working.
Thanks to #Kazar for this answer here https://stackoverflow.com/a/2070493/3790921 and #Pranay Rana for this answer here https://stackoverflow.com/a/3801289/3790921
I put this together...
con.Open();
byte[] pict = (byte[])cmd.ExecuteScalar();
con.Close();
ctx.Response.ContentType = "image/bmp";
if (pict.Length <= 1) {
// the BLOB is not a picture
byte[] txt = ImageToByteArray(DrawText("no image found"));
ctx.Response.OutputStream.Write(txt, 0, txt.Length);
} else {
// stream the picture data from BLOB
ctx.Response.OutputStream.Write(pict, 0, pict.Length);
}
and it is working.

Store image on SQL Server, from stream on PictureBox control

I´ve stream video on a pictureBox control, and I want to get image from PictureBox, to store on a table on SQL Server. PictureBox show stream but, PictureBox retrieve null.
What is wrong?
private void button1_Click(object sender, EventArgs e){
SqlConnection con = new SqlConnection("Data Source=IBM-PC\\SQLEXPRESS2;Initial Catalog=DBACCESS;Integrated Security=True");
if (cmrConductor.Image == null){
mensajeOK("Error");
}else{
MemoryStream ms = new MemoryStream();
cmrConductor.Image.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
byte[] Pic_arr = new byte[ms.Length];
ms.Position = 0;
ms.Read(Pic_arr, 0, Pic_arr.Length);
SqlCommand cmd = new SqlCommand("INSERT INTO tblUsers (fldCode, fldPic) VALUES (#fldCode, #fldPic)", con);
cmd.Parameters.AddWithValue("#fldCode", txtId.Text);
cmd.Parameters.AddWithValue("#fldPic", Pic_arr);
con.Open();
try{
int res = cmd.ExecuteNonQuery();
if (res > 0){
MessageBox.Show("insert");
}
}
catch (Exception ex){
MessageBox.Show(ex.Message);
}
finally{
con.Close();
}
}
}
You need to set your image field type as varbinary(MAX) and you need to convert your image into a byte array before inserting.
//Insert image
SqlCommand comm = new SqlCommand("Insert into ImageColumn values (#Image)")
comm.Parameters.AddWithValue("#Image", Converter.GetBytes(pictureBox.image));
//Retrieving image
pictureBox1.Image = Converter.GetImage(dataTable.Rows[0]["ImageColumn"])
//Converter class
class Converter
{
public static byte[] GetBytes(System.Drawing.Image imageIn)
{
using (var ms = new MemoryStream())
{
imageIn.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
return ms.ToArray();
}
}
public static byte[] GetBytes(string path)
{
using (var ms = new MemoryStream())
{
Image img = Image.FromFile(path);
img.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
return ms.ToArray();
}
}
public static Image GetImage(byte[] buffer)
{
using (var ms = new MemoryStream(buffer))
{
return Image.FromStream(ms);
}
}
}
Here is the solution, thanks to this post Saving Panel as an Image. I just had to change PictureBox control by a Panel control.
private void button1_Click(object sender, EventArgs e){
SqlConnection con = new SqlConnection("Data Source=IBM-PC\\SQLEXPRESS2;Initial Catalog=DBACCESS;Integrated Security=True");
MemoryStream ms = new MemoryStream();
Bitmap bmp = new Bitmap(cmrConductor.Width, cmrConductor.Height);
cmrConductor.DrawToBitmap(bmp, cmrConductor.Bounds);
bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
byte[] Pic_arr = new byte[ms.Length];
ms.Position = 0;
ms.Read(Pic_arr, 0, Pic_arr.Length);
SqlCommand cmd = new SqlCommand("INSERT INTO tblUsers (fldCode, fldPic) VALUES (#fldCode, #fldPic)", con);
cmd.Parameters.AddWithValue("#fldCode", txtId.Text);
cmd.Parameters.AddWithValue("#fldPic", Pic_arr);
con.Open();
try
{
int res = cmd.ExecuteNonQuery();
if (res > 0)
{
MessageBox.Show("insert");
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
con.Close();
}
}

How to retrieve image from Oracle database using C# web application?

I want to retrieve an image from an Oracle database to an Image control in asp.net. I tried but it's not working.
This is the code used for inserting image into database:
protected void btnUpload_Click(object sender, EventArgs e)
{
int imgLength = 0;
string imgContentType = null;
string imgFileName = null;
Stream imgStream = FileUpload.PostedFile.InputStream;
imgLength = FileUpload.PostedFile.ContentLength;
imgContentType = FileUpload.PostedFile.ContentType;
imgFileName = FileUpload.PostedFile.FileName;
if (imgContentType == "image/jpeg" || imgContentType == "image/gif" ||
imgContentType == "image/pjpeg"
|| imgContentType == "image/bmp")
{
OracleConnection DbConnection = new OracleConnection(con1);
DbConnection.Open();
FileStream fls;
fls = new FileStream(#imgFileName, FileMode.Open, FileAccess.Read);
byte[] blob = new byte[fls.Length];
fls.Read(blob, 0, System.Convert.ToInt32(fls.Length));
fls.Close();
string query = "insert into image(id,name,photo) values(1,'" + imgFileName + "'," + " :BlobParameter )";
// Establish a new OracleCommand
OracleCommand cmd = new OracleCommand();
cmd.CommandText = query;
cmd.Connection = DbConnection;
cmd.CommandType = CommandType.Text;
System.Data.OracleClient.OracleParameter paramImage = new System.Data.OracleClient.OracleParameter("image",
Oracle.DataAccess.Client.OracleDbType.Blob);
paramImage.ParameterName = "BlobParameter";
paramImage.Value = blob;
paramImage.Direction = ParameterDirection.Input;
cmd.Parameters.Add(paramImage);
cmd.ExecuteNonQuery();
}
Table:
Id Name Photo
1 C:\\user\pictures\animal.jpeg (BLOB)
Below is the code used to retrieve the image into an image control but this code is not working.
For the past two days I've been struggling with this
void GetImagesFromDatabase()
{
try
{
OracleConnection DbConnection = new OracleConnection(con1);
DbConnection.Open();
OracleCommand cmd = new OracleCommand("Select name,photo from Image", DbConnection);
OracleDataReader oda = cmd.ExecuteReader();
while (oda.Read())
{
string path = oda[0].ToString();
img.ImageUrl = path;
if(oda.GetValue(1).ToString() !=""){
FileStream fls;
fls = new FileStream(#path, FileMode.Open, FileAccess.Read);
byte[] blob = new byte[fls.Length];
fls.Read(blob, 0, System.Convert.ToInt32(fls.Length));
fls.Close();
MemoryStream memStream = new MemoryStream(blob);
img.ImageUrl = oda[2].ToString();
}
}
}
catch (Exception ex)
{
}
}
Any ideas? Thanks in advance
maybe this code can help you:
public Image byteArrayToImage(byte[] byteArrayIn)
{
MemoryStream ms = new MemoryStream(byteArrayIn);
Image returnImage = Image.FromStream(ms);
return returnImage;
}

Convert from binary data to an image control in ASP.NET

I have binary data of an image in my database, and I want to display it in an image control in ASP.NET. How? If it is impossible, please find another way to save it in the database and display it in an image control.
Create a regular HTML img element like so:
<img runat="server" id="image" />
And in code behind do this:
image.src = "data:image/png;base64," + Convert.ToBase64String(imageBytes);
Where imageBytes is a byte[].
You are done. The image will be displayed.
Most likely the image is being stored as a byte array in the database. If so, then you can use this:
public static System.Drawing.Image ByteArrayToImage(byte[] bArray)
{
if (bArray == null)
return null;
System.Drawing.Image newImage;
try
{
using (MemoryStream ms = new MemoryStream(bArray, 0, bArray.Length))
{
ms.Write(bArray, 0, bArray.Length);
newImage = System.Drawing.Image.FromStream(ms, true);
}
}
catch (Exception ex)
{
newImage = null;
//Log an error here
}
return newImage;
}
public Byte[] Ret_image(Int32 id)
{
SqlCommand cmd = new SqlCommand();
cmd.CommandText = "select * from tbimage where imageid=#id";
cmd.Connection = con;
cmd.Parameters.Add("#id", SqlDbType.Int).Value = id;
SqlDataReader dr = cmd.ExecuteReader();
dr.Read();
Byte[] ar = (Byte[])(dr[1]);
dr.Close();
cmd.Dispose();
return ar;
}
protected void Button2_Click(object sender, EventArgs e)
{
Byte[] ar = Ret_image(Convert.ToInt32(TextBox2.Text));
String st = Server.MapPath("abc.jpg");
FileStream fs = new FileStream(st, FileMode.Create, FileAccess.Write);
fs.Write(ar, 0, ar.Length);
fs.Close();
Image1.ImageUrl = "abc.jpg";
}
Use this event for the button click to retrieve image and call the Ret_Image method here.
In a generic handler (.ashx):
public class ImageHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
if(!string.IsNullOrEmpty(context.Request.QueryString["ImageId"]))
{
try
{
string ImageId = context.Request.QueryString["ImageId"].ToString();
ImageDataModel idm = new ImageDataModel();
byte[] ImageData = idm.getImageData(ImageId);
context.Response.ContentType = "image/JPEG";
context.Response.OutputStream.Write(ImageData, 0, ImageData.Length);
}
catch(Exception ex){}
}
}
}
SqlConnection con = new SqlConnection();
string _path;
Using SYstem.IO;
Using System.Data.SQLClient;
//convert Image to binary and save in DB
private void button1_Click(object sender, EventArgs e)
{
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
_path = openFileDialog1.FileName;
InsertInSQL(_path);
}
}
private void InsertInSQL(string _path)
{
con.ConnectionString = Pic.Properties.Settings.Default.ConnectionS;
string strQ = "insert into dbo.PicTBL(Pic)values(#p)";
SqlCommand command = new SqlCommand(strQ,con);
command.Parameters.AddWithValue("#p",ImageToBinary(_path));
con.Open();
command.ExecuteNonQuery();
con.Close();
}
public static byte[] ImageToBinary(string _path)
{
FileStream fS = new FileStream(_path, FileMode.Open, FileAccess.Read);
byte[] b = new byte[fS.Length];
fS.Read(b, 0, (int)fS.Length);
fS.Close();
return b;
}
//Convert Binary to imge and save in a folder
private void button1_Click_1(object sender, EventArgs e)
{
DataTable dt = Rimage();
foreach (DataRow row in dt.Rows)
{
byte[] b = (byte[])row["Pic"];
Image img = BinaryToImage(b);
img.Save("D:\\NewFolder\\" + row["ID"].ToString() + ".jpg");
}
}
private Image BinaryToImage(byte[] b)
{
if (b == null)
return null;
MemoryStream memStream = new MemoryStream();
memStream.Write(b, 0, b.Length);
return Image.FromStream(memStream);
}
private DataTable Rimage()
{
con.ConnectionString = Pic.Properties.Settings.Default.ConnectionS;
SqlCommand cmd = new SqlCommand();
cmd.CommandText = "select * from dbo.PicTBL";
cmd.Connection = con;
SqlDataAdapter adp = new SqlDataAdapter(cmd);
DataTable dt = new DataTable();
con.Open();
adp.Fill(dt);
return dt;
}

OutOfMemoryException was unhandled Image.FromFile() in C#

i got out of memory exception upon loading image from file.. i retrieve the file from database and the output file image can be viewed..
String temp = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "/img.jpg";
using (FileStream fs = new FileStream(temp, FileMode.Create))
{
fs.Write(StudentImage(id), 0, StudentImage(id).Length);
fParent.picAvatar.BackgroundImage = Image.FromFile(temp);
//fParent.picAvatar.Image = Image.FromFile(temp2);
}
private byte[] StudentImage(String _id)
{
try
{
String sqlCmd = String.Format("SELECT studpic FROM dbo.studentpic WHERE idnum = '{0}'", _id);
using (SqlConnection con = new SqlConnection(gVar._conString))
{
con.Open();
SqlCommand cmd = new SqlCommand(sqlCmd, con);
using (SqlDataReader r = cmd.ExecuteReader())
{
r.Read();
byte[] imgData = (byte[])r["studpic"];
return imgData;
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
return null;
}
}
did i miss any object that needs to close?
You tend to get an OutOfMemory exception when an image cannot be read for a number of reasons.
In your case the issue is that you have not closed your file! Also, you are calling the database twice.
I suggest the following code:
File.WriteAll(temp, StudentImage(id));
fParent.picAvatar.Image = Image.FromFile(temp);

Categories

Resources