How to add image from Database in Crystal Report viewer? - c#

Hello I have saved an image in my database field and want to display that image in my crystal report viewer but unable to figure out how to perform it? Any help or suggestion will be very helpful.

Ok I was using SQLite and important thing that is to be done is to create
1.) A BLOB field to save your data is to be used.
2.) Use the following code to select the file. For this one need to call the Open Dialog Box.
{
OpenFileDialog of1 = new OpenFileDialog();
of1.Filter = "JPEG Files (*.jpeg)|*.jpeg|PNG Files (*.png)|*.png|JPG Files (*.jpg)|*.jpg";
of1.ShowDialog();
tbImage.Text = of1.FileName;
}
Note: Don't forget to set the related Database Field type as System.byte[];
3.) Now convert the file into Byte Stream.
{
byte[] imageBt = null;
FileStream fstream = new FileStream(tbImage.Text,FileMode.Open,FileAccess.Read);
BinaryReader br = new BinaryReader(fstream);
imageBt = br.ReadBytes((int)fstream.Length);
}
4.) Insert the image in the database
{
String query = "Insert into Employee Values (" + e1.EmpID + ",'" + e1.FirstName + "','" + e1.LastName + "','" + e1.EmailAddress + "', #IMG)";
myCommand = new SQLiteCommand(query, dbConn);
myCommand.Parameters.Add(new SQLiteParameter("#IMG", e1.Image));
}
For Retrieval of the images first an ImageBox is required
1.) Use the following code to get the BLOB data byte and to place the image in the Image Box
{
MemoryStream mstream = new MemoryStream((byte[])(reader["Image"]));
ImageBox.Image = System.Drawing.Image.FromStream(mstream);
}

Related

Certain files created from MemoryStream are corrupt

I have code that passes a list of objects containing the filename and binary data from the db to a loop that creates all the files. The problem that I have is the code below executes and appears to create the files correctly (filename & size is as expected) however, most files are "corrupt" when opened. The file types vary from images (jpg/png) to Word documents, Powerpoint presentations and PDF files. What is strange is that PDF files work perfectly, everything else is "corrupt"
My code is below (attachment is the object in the loop, the path is already created at this stage)
if(Directory.Exists(attachmentPath))
{
string absolutePath = attachmentPath + "\\importfiles\\" + parentfolders + "\\";
// no need to check if it exists as it will ignore if it does
Directory.CreateDirectory(absolutePath);
absolutePath += filename;
try
{
byte[] byteStream = null;
object objSave = null;
objSave = attachment.Image;
BinaryFormatter tmpBinF = new BinaryFormatter();
MemoryStream tmpMemStrm = new MemoryStream();
tmpBinF.Serialize(tmpMemStrm, objSave);
byteStream = tmpMemStrm.ToArray();
// Delete the file if it exists.
if (File.Exists(absolutePath))
{
File.Delete(absolutePath);
}
// Create the file.
using (FileStream fs = File.Create(absolutePath))
{
fs.Write(byteStream, 0, byteStream.Length);
fs.Dispose();
}
}
catch (Exception ex)
{
Exceptions.Text += ex.ToString();
}
}
I've used tips from MSDN and followed this tutorial but can't figure out why this is happening.
Thanks go to Amy for pointing out the issue with my approach, if anyone needs it, here's my updated code taking her answer into account. I've also extended it to add a log record on a table in the DB for later use.
if (Directory.Exists(attachmentPath))
{
// build path from the parts
string absolutePath = attachmentPath + "\\importfiles\\" + parentfolders + "\\";
// no need to check if it exists as it will ignore if it does
Directory.CreateDirectory(absolutePath);
absolutePath += filename;
byte[] file = attachment.Image;
try
{
// Delete the file if it exists.
if (File.Exists(absolutePath))
{
File.Delete(absolutePath);
}
// Create the file.
using (FileStream fs = File.Create(absolutePath))
{
fs.Write(file, 0, file.Length);
}
// start logging to the database
// add the Stored procedure
string SP = "sp_add_attachment";
// create the connection & command objects
MySqlConnection myConnection1 = new MySqlConnection(WPConnectionString);
MySqlCommand cmd1;
try
{
// open the connection
myConnection1.Open();
cmd1 = myConnection1.CreateCommand();
// assign the stored procedure string to the command
cmd1.CommandText = SP;
// define the command type
cmd1.CommandType = CommandType.StoredProcedure;
// pass the parameters to the Store Procedure
cmd1.Parameters.AddWithValue("#AttachmentID", attachment.ID);
cmd1.Parameters["#AttachmentID"].Direction = ParameterDirection.Input;
cmd1.Parameters.AddWithValue("#subpath", parentfolders);
cmd1.Parameters["#subpath"].Direction = ParameterDirection.Input;
cmd1.Parameters.AddWithValue("#filename", filename);
cmd1.Parameters["#filename"].Direction = ParameterDirection.Input;
// execute the command
int output = cmd1.ExecuteNonQuery();
// close the connection
myConnection1.Close();
}
catch (Exception ex)
{
Exceptions.Text += "MySQL Exception when logging:" + ex.ToString();
}
}
catch (Exception ex)
{
Exceptions.Text += ex.ToString();
}
}
I don't think using the BinaryFormatter is appropriate. If attachment.Image is a byte array, simply write it to the filestream. Forget the memory stream and the binary formatter entirely.
The Binary Formatter class is used to serialize a .Net class into a byte array. You already have a byte array though, so that step is not needed and is the source of your problem. Using the binary formatter would be appropriate only if the same binary formatter was used to create the blobs in the database. But you're storing files, not .Net objects, so it isn't useful here.
I'm not sure why PDFs would load when other files won't. You'd have to inspect the file using a hex editor to see what changed.

Adding a picture to a checkbox list after binding

Is there any way to populate a checkbox list through datasource/ databind and then actually add an image to each checkbox? i know how to do both separately but cant seem to figure out how to make them work together.
Essentially i will have a checkbox list of students for teachers to select from and i've been asked to put a picture of each student next to the checkbox.
The way i get images currently is i have a webform which intakes an ID in the url and then it grabs the blob off the database then converts the binary into a thumbnail image, saves that locally then redirects to it. then when i want to get an image on a different webform i just need to use Response.Redirect("imgs.aspx?ID=[Student Id]") and it will put in a small image of the student, is there any way to modify a checkbox list so that i can call on the imgs webform and display the image of the student next to their checkbox?
Code behind imgs.aspx:
protected void Page_Load(object sender, EventArgs e)
{
var stuId = Request.QueryString["ID"];
if (stuId.Length <= 0)
{
stuId = "100097645"; // If no ID number sent, display default 'image not available' thumbnail.
}
var con = new SqlConnection
{
ConnectionString =
removed for security reasons
};
con.Open();
var sqlCommand = new SqlCommand("Select BINARY_OBJECT FROM BLOBS WHERE OWNER_REF=" + stuId, con);
var reader = sqlCommand.ExecuteReader(CommandBehavior.CloseConnection);
reader.Read();
var byteArray = (byte[])reader["BINARY_OBJECT"];
var mstream = new System.IO.MemoryStream(byteArray, 0, byteArray.Length);
var dbImage = System.Drawing.Image.FromStream(new System.IO.MemoryStream(byteArray));
var thumbnailImage = dbImage.GetThumbnailImage(100, 100, null, new IntPtr());
thumbnailImage.Save(mstream, dbImage.RawFormat);
var thumbnailByteArray = new byte[mstream.Length];
mstream.Position = 0;
mstream.Read(thumbnailByteArray, 0, Convert.ToInt32(mstream.Length));
Response.Clear();
Response.BinaryWrite(thumbnailByteArray);
}
code i have so far to display the image:
private void StudentSelected()
{
string query = "Select distinct (Convert(varchar, PERSON_CODE) + '|' + FORENAME + ' ' + SURNAME) as StudentName, (Convert(varchar, PERSON_CODE) + '|' + FORENAME + '|' + SURNAME) as StudentValue From people where (FORENAME = '" + stuforename + "') and (SURNAME = '" + stusurname + "') and (Convert(varchar,PERSON_CODE) = '" + stuid + "')";
StudentCheckBoxData.Merge(GetData(query));
cbSelection.DataSource = StudentCheckBoxData;
cbSelection.DataTextField = "StudentName";
cbSelection.DataValueField = "StudentValue";
cbSelection.DataBind();
try
{
foreach (ListItem checkBox in cbSelection.Items)
{
checkBox.Text += string.Format("<img src = \"{0}\" /> ", GetImageUrl(checkBox.Text.Split('|')[0]));
}
}
catch
{
//Display Error Here
}
}
private string GetImageUrl(string id)
{
return string.Format("http://bceforms/Contact/imgs.aspx?ID=", id);
}
The problem at the moment is it shows the border but the image that appears is a Thumbnail not found image, when i've had this issue before it's been because image hasn't been databound however when i then use .databind(); on the checkbox List because it obviously the original datasource doesn't have the image, it just removes the image
Any help would be apprecieated
I do not think it is a good way in performance to save image data in sql, Instead you can save the image url in the sql and save the image file. And at the end of your code you have a problem:
private string GetImageUrl(string id)
{
return string.Format("http://bceforms/Contact/imgs.aspx?ID=", id);
}
You must change that to this:
private string GetImageUrl(string id)
{
return string.Format("http://bceforms/Contact/imgs.aspx?ID={0}", id);
}
After fixing this, Please let know the result.

Using the UPDATE MySQL Command in C#

Suppose I have this method from one class:
private void btnChangeImage_Click(object sender, EventArgs e)
{
using (var openFileDialogForImgUser = new OpenFileDialog())
{
string location = null;
string fileName = null;
openFileDialogForImgUser.Filter = "Image Files (*.jpg, *.png, *.gif, *.bmp)|*.jpg; *.png; *.gif; *.bmp|All Files (*.*)|*.*"; // filtering only picture file types
var openFileResult = openFileDialogForImgUser.ShowDialog(); // show the file open dialog box
if (openFileResult == DialogResult.OK)
{
using (var formSaveImg = new FormSave())
{
var saveResult = formSaveImg.ShowDialog();
if (saveResult == DialogResult.Yes)
{
imgUser.Image = new Bitmap(openFileDialogForImgUser.FileName); //showing the image opened in the picturebox
location = openFileDialogForImgUser.FileName;
fileName = openFileDialogForImgUser.SafeFileName;
FileStream fs = new FileStream(location, FileMode.Open, FileAccess.Read); //Creating a filestream to open the image file
int fileLength = (int)fs.Length; // getting the length of the file in bytes
byte[] rawdata = new byte[fileLength]; // creating an array to store the image as bytes
fs.Read(rawdata, 0, (int)fileLength); // using the filestream and converting the image to bits and storing it in an array
MySQLOperations MySQLOperationsObj = new MySQLOperations("localhost", "root", "myPass");
MySQLOperationsObj.saveImage(rawdata);
fs.Close();
}
else
openFileDialogForImgUser.Dispose();
}
}
}
}
And this method from another class (MySQLOperations):
public void saveImage(byte[] rawdata)
{
try
{
string myConnectionString = "Data Source = " + server + "; User = " + user + "; Port = 3306; Password = " + password + ";";
MySqlConnection myConnection = new MySqlConnection(myConnectionString);
string currentUser = FormLogin.userID;
string useDataBaseCommand = "USE " + dbName + ";";
string updateTableCommand = "UPDATE tblUsers SET UserImage = #file WHERE Username = \'" + currentUser + "\';";
MySqlCommand myCommand = new MySqlCommand(useDataBaseCommand + updateTableCommand, myConnection);
myCommand.Parameters.AddWithValue("#file", rawdata);
myConnection.Open();
myCommand.ExecuteNonQuery();
myConnection.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error!", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
If I must, this is my constructor for the MySQLOperations class:
public MySQLOperations(string server, string user, string password)
{
this.server = server;
this.user = user;
this.password = password;
}
What I'm trying to do is save an image file (which the user selects through the open file dialog box) to the database. Problem is I get this error: "You have an error in your SQL syntax; check the manual that correponds to your MySQL server version for the right syntax to use near ';UPDATE tblUsers SET UserImage = _binary'?PNG ... (and so on with some random characters). So, I can't really save the file in the database. I would love to post a picture on how the error is seen at the MessageBox, but I guess my account is not given the privilege to do so yet.
I'm not really sure where the syntax error is in that. I'm thinking, it's in the #file - but that's just a guess. Your help would be very much appreciated.
And oh, the table column UserImage has a type of LONGBLOB.
Other things I'm interested to know about also:
Is it necessary that I add another column for my table to store the
size of the file (because I'm going to need to retrieve the file
to display the image later on)?
Is it okay that I used the using statement that way in the method
btnChangeImage_Click?
Thank you very much.
EDIT: Got the problem solved. Such a simple thing not given attention to. Thanks to everybody who tried to help. I'm still willing to hear your opinion on the questions at the bottom (those on bullets).
I think the problem is in the following line of code:
WHERE Username = \'" + currentUser + "\';"
It should change to the following one:
WHERE Username = " + currentUser;
Or better (to avoid sql injections) to the following one:
WHERE Username = #Username";
myCommand.Parameters.AddWithValue("#Username", currentUser);
Do not store binary files in a MySQL table. Instead, save it to disk and save path to PNG file to MySQL database. Also, use Christos advice to avoid SQL injections.

save png file in application image folder in silverlight

I save a png file using silverlight. But I want to save it in application IMG folder. My code is as follows:
if (lastSnapshot != null)
{
string ImageName = DateTime.Now.Year.ToString() + DateTime.Now.Month.ToString() + DateTime.Now.Day.ToString() + DateTime.Now.Hour.ToString()
+ DateTime.Now.Minute.ToString() + DateTime.Now.Second.ToString() + DateTime.Now.Millisecond.ToString() + ".png";
string filePath=System.IO.Path.Combine("~/Images/", "" + ImageName + "");
using (var pngStream = GetPngStream(lastSnapshot))
using (var file = File.Create(filePath))
{
byte[] binaryData = new Byte[pngStream.Length];
long bytesRead = pngStream.Read(binaryData, 0, (int)pngStream.Length);
file.Write(binaryData, 0, (int)pngStream.Length);
file.Flush();
file.Close();
}
}
I want to do it in silverlight. Can I do it? Can I save file directly in application folder? How to do it? I'll be grateful to anyone who will help me. Thanks in advance.
Adjacent question of mine
You will have to provide a webservice or upload url at the server side and use that from within Silverlight at the client.
Silverlight applications to NOT have direct access the the server's folders because Silverlight executes at the client.

save user profile image to database

How can I dynamically insert images when user uploads an image file to SQL Server 2005 with C# in ASP.NET? This is to let users upload their profile photos in my web app. Is it very different from how it is done for windows app with C#?
There is a metric ton of examples on the web on this one:
http://aspalliance.com/138
https://web.archive.org/web/20210304133428/https://www.4guysfromrolla.com/articles/120606-1.aspx
http://www.aspfree.com/c/a/ASP.NET/Uploading-Images-to-a-Database--C---Part-I/
You should be able to follow any of those to accomplish what you want.
The same way as in in WinForms. Get byte[] and same to image column. But i strongly recommend to use file system to store pictures. DB is for relational data, File System for raw bytes.
http://msdn.microsoft.com/en-us/library/aa479405.aspx
Here is a sample of the code behind for inserting an image into a database in C#. You will of coarse need supporting table the picture should be a byte field and keep the picture type so you can retrieve the image later to display it. In addition to that you need to put a file input box on your page along with a submit button.
public void AddImage(object sender, EventArgs e)
{
int intImageSize;
String strImageType;
Stream ImageStream;
FileStream fs = File.OpenRead(Request.PhysicalApplicationPath + "/Images/default_image.png");
Byte[] ImageContent;
if (PersonImage.PostedFile.ContentLength > 0)
{
intImageSize = PersonImage.PostedFile.ContentLength;
strImageType = PersonImage.PostedFile.ContentType;
ImageStream = PersonImage.PostedFile.InputStream;
ImageContent = new Byte[intImageSize];
int intStatus;
intStatus = ImageStream.Read(ImageContent, 0, intImageSize);
}
else
{
strImageType = "image/x-png";
ImageContent = new Byte[fs.Length];
fs.Read(ImageContent, 0, ImageContent.Length);
}
SqlConnection objConn = new SqlConnection(ConfigurationManager.AppSettings["conn"]);
SqlCommand objCmd;
string strCmd;
strCmd = "INSERT INTO ImageTest (Picture, PictureType) VALUES (#Picture, #PictureType)";
objCmd = new SqlCommand(strCmd, objConn);
SqlParameter prmPersonImage = new SqlParameter("#Picture", SqlDbType.Image);
prmPersonImage.Value = ImageContent;
objCmd.Parameters.Add(prmPersonImage);
objCmd.Parameters.AddWithValue("#PictureType", strImageType);
lblMessage.Visible = true;
try
{
objConn.Open();
objCmd.ExecuteNonQuery();
objConn.Close();
lblMessage.Text = "ImageAdded!";
}
catch
{
lblMessage.Text = "Error occured the image has not been added to the database!";
}
}

Categories