Download image file from datapath stored in SQL Server database - c#

I am creating a web form application that allows a user to upload image file to a folder and store its path in a database. There is a data-list that is populated by the image path. I want the functionality to download image when it is selected from data-list. I am new to it and didn't get clear guidance from other questions.
Kindly help me.
Here is my code for uploading file
try
{
if (FileUploadzz.HasFile)
{
Guid g = Guid.NewGuid();
string strguid = g.ToString();
string uniqueString = strguid + FileUploadzz.FileName;
FileUploadzz.SaveAs(Server.MapPath(#"~\AllUploads\AllUserImages\" + uniqueString));
DataClasses1DataContext db2 = new DataClasses1DataContext();
Picture p = new Picture();
p.picturePath = "http://localhost:12237/AllUploads//AllUserImages/" + uniqueString;
db2.Pictures.InsertOnSubmit(p);
db2.SubmitChanges();
}
}
catch (Exception)
{
throw;
}
I have a button in my datalist itemtemplate that I want to use for downloading that specific image I need help on downloading the image when button is clicked. I have image control and a button (button1) in item template of datalist. I have already populated my datalist succesfully with images. please let me know how to download that image on OnCLlick event of that button1.

This code works in a way like you've to pass and image id to the function and w.r.t. that you can fetch specific image. This code will act like a base. If you want to fetch all the images at same time then still you can do using while loop. You can do deserializing one by one. So according to your purpose small changes need to be done.
private System.Windows.Forms.PictureBox picImage;
SqlConnection con = new SqlConnection(GetConnectionString());
SqlCommand cmd = new SqlCommand("ReadImage", con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#imgId", SqlDbType.Int).Value = Convert.ToInt32(cmbImageID.SelectedValue.ToString());
SqlDataAdapter adp = new SqlDataAdapter(cmd);
DataTable dt = new DataTable();
try
{
if (con.State == ConnectionState.Closed)
con.Open();
adp.Fill(dt);
if (dt.Rows.Count > 0)
{
MemoryStream ms = new MemoryStream((byte[])dt.Rows[0]["ImageData"]);
picImage.Image = Image.FromStream(ms);
picImage.Image.Save(#"Complete path of location", ImageFormat.Jpeg);
}
}
catch (Exception ex)//catch if any error occur
{
MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
finally
{
if (con.State == ConnectionState.Open)//check whether connection to database is open or not
con.Close();
}
}

Related

Converting stored images in DB to string and back to byte?

So I have a couple tabs in a tabcontrol which do the task of registering and modifying info about a client. The first one among other info, saves a picture using OpenFileDialog and then store it into 'lblImagePath.Text' to use bitmap with it so I can save it into de DB, which can be seen in this code:
public partial class form : Form
{
String strDBFilePath = "";
String strFilePath = "";
Image DefaultImage;
byte[] ImageByteArray;
byte[] ImageByteArrayMod;
private void btnAddUser_Click(object sender, EventArgs e)
{
if (txtEmailPersonal.Text != "")
{
try
{
Image temp = new Bitmap(strFilePath);
MemoryStream ms = new MemoryStream();
temp.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
ImageByteArray = ms.ToArray();
SqlConnection con = new SqlConnection();
con.ConnectionString = CONEXION.CONEXIONMAESTRA.conexion;
con.Open();
SqlCommand cmd = new SqlCommand();
cmd = new SqlCommand("insert_user", con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#email", txtEmailPersonal.Text);
cmd.Parameters.AddWithValue("#password", txtPasswordPersonal.Text);
cmd.Parameters.AddWithValue("#profile_picture", ImageByteArray);
cmd.Parameters.AddWithValue("#imageFile_name", lblImagePath.Text);
cmd.ExecuteNonQuery();
con.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
mostrar();
}
}
}
Everything goes smooth, register form works and I'm using a datagridview to visualize it. When I double click a row from the dgv, all the info loads into the second tab and let's me modify all the info except the profile picture, which can be previewed in a picturebox but doesnt load any other information about it, so when I hit the 'save changes' button, it won't let me proceed with it until I re-upload a profile picture, since path is non existant prior to that action. This is the code for user modifying:
private void btnGuardarCambiosPersonal_Click(object sender, EventArgs e)
{
if (txtEmailPersonalMod.Text != "")
{
try
{
Image temp = new Bitmap(strDBFilePath);
MemoryStream ms = new MemoryStream();
temp.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
ImageByteArrayMod = ms.ToArray();
SqlConnection con = new SqlConnection();
con.ConnectionString = CONEXION.CONEXIONMAESTRA.conexion;
con.Open();
SqlCommand cmd = new SqlCommand();
cmd = new SqlCommand("modify_user", con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#correo", txtEmailPersonalMod.Text);
cmd.Parameters.AddWithValue("#password", txtPasswordPersonalMod.Text);
cmd.Parameters.AddWithValue("#profile_picture", ImageByteArrayMod);
cmd.Parameters.AddWithValue("#imageFile_name", lblFilePathMod.Text);
cmd.ExecuteNonQuery();
con.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
mostrar();
}
}
Some of the stuff I have in there might actually be useless to accomplish what I want. So I'll try to be as clear as possible, I want to be able to keep the current profile picture if another profile picture isn't uploaded to replace it.
As you might also see, instead of doing the query directly on the code, I'm using stored procedures, the idea is to keep those stored procedures and try to do the adjusting in the code.
After reading #Llama 's comments, I realized solution was very simple, over the modifying code, I added this at the beginning of the try/catch:
Image tempy = new Bitmap(picPerfilMod.Image);
MemoryStream mems = new MemoryStream();
tempy.Save(mems, System.Drawing.Imaging.ImageFormat.Jpeg);
ImageByteArrayMod = mems.ToArray();
so I could turn image from picturebox back to array and without the need to modify it.
I will keep reading about varbinary column type use for this cases, since it clearly looks like a better/simpler idea.

Retrieved saved file from SQL database when editing a form in asp.net

I have a form where a user can capture information about an invoice. As part of that form the user can upload and save a pdf file copy of that invoice into the database.
I am using the same form to save a new invoice and to edit already captured invoices.
The problem I have is that when a user edits an already existing invoice and saves their changes, the pdf file invoice is overwritten with a blank.
I am not sure how to solve this problem and retrieve the already saved pdf file invoice so that when the user saves their changes the pdf file invoice doesn't get overwritten with a blank.
This is what I have so far:
public void PopulateForm()
{
SqlConnection con = new SqlConnection(
WebConfigurationManager.ConnectionStrings["MyDbConn"].ConnectionString);
con.Open();
SqlDataReader myReader = null;
SqlCommand cmd = new SqlCommand("sp_displayVsoftInvoice", con);
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("VSoftInvoiceID", txtID.Text);
myReader = cmd.ExecuteReader();
while (myReader.Read())
{
txtInvoiceNo.Text = (myReader["InvoiceNo"].ToString());
ddlInvoiceType.SelectedValue = (myReader["EventTypeID"].ToString());
txtDateSent.Text = (myReader["DateSent"].ToString());
txtDatePaid.Text = (myReader["DatePaid"].ToString());
string InvSent = (myReader["InvoiceSent"].ToString());
string InvPaid = (myReader["InvoicePaid"].ToString());
if (InvSent == "True")
{
cbxInvSent.Checked = true;
}
if (InvPaid == "True")
{
cbxInvPaid.Checked = true;
}
}
con.Close();
}
protected void btnSaveInvoice_Click(object sender, EventArgs e)
{
string filename = Path.GetFileName(FileUpload1.PostedFile.FileName);
string contentType = FileUpload1.PostedFile.ContentType;
using (Stream fs = FileUpload1.PostedFile.InputStream)
{
using (BinaryReader br = new BinaryReader(fs))
{
byte[] bytes = br.ReadBytes((Int32)fs.Length);
SqlConnection con = new SqlConnection(
WebConfigurationManager.ConnectionStrings["MyDbConn"].ConnectionString);
con.Open();
SqlCommand cmd = new SqlCommand("sp_insertUpdateVsoftInvoice", con);
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("VSoftInvoiceID", txtID.Text);
cmd.Parameters.AddWithValue("CenterID", ddlCenter.SelectedItem.Value);
cmd.Parameters.AddWithValue("InvoiceTypeID", ddlInvoiceType.SelectedItem.Value);
cmd.Parameters.AddWithValue("InvoiceNo", txtInvoiceNo.Text);
cmd.Parameters.AddWithValue("InvoiceSent", this.cbxInvSent.Checked ? "1" : "0");
cmd.Parameters.AddWithValue("InvoicePaid", this.cbxInvPaid.Checked ? "1" : "0");
cmd.Parameters.AddWithValue("DateSent", txtDateSent.Text);
cmd.Parameters.AddWithValue("DatePaid", txtDatePaid.Text);
cmd.Parameters.AddWithValue("InvoiceName", filename);
cmd.Parameters.AddWithValue("ContentType", contentType);
cmd.Parameters.AddWithValue("Data", bytes);
cmd.Parameters.AddWithValue("ModifiedBy", txtUser.Text);
cmd.Parameters.AddWithValue("DateModified", DateTime.Now);
cmd.ExecuteNonQuery();
con.Close();
Response.Redirect("VsoftInvoice.aspx");
}
}
}
Please advise me on how I can solve this problem so that my already saved pdf invoice doesn't get overwritten with a blank.
Thanks in advance!
We need to clarify one of two things:
1- is that happening when editing without uploading a document?if yes then I think you need to save the file only when there is file uploaded (modifying your btnSaveInvoice_Click method)
2- if there is another edit method then please share the code
Good luck further.

How to prevent my gridview from creating additional rows in c#?

I try researching this everywhere but it appears when I run my windows form application and display my database. Each it keeps automatically skipping and adding rows.
Here is a screen shot of my gridview
Here is also my code where it displays the database when I click a button:
try
{
conn = new MySqlConnection();
conn.ConnectionString = connstring;
query = "INSERT INTO schedule(name) VALUES(#namevalue)";
MySqlCommand cmd = new MySqlCommand(query, conn);
cmd.Parameters.AddWithValue("#namevalue", this.nameEmp.Text);
conn.Open();
cmd.ExecuteNonQuery();
MessageBox.Show("Connection Success");
myadapt = new MySqlDataAdapter();
string sq = "SELECT * FROM schedule";
myadapt.SelectCommand = new MySqlCommand(sq, conn);
tb = new DataTable();
myadapt.Fill(tb);
BindingSource src = new BindingSource();
src.DataSource = tb;
dataGridView1.DataSource = src;
}
catch (MySqlException ex)
{
MessageBox.Show(ex.Message);
}
}
Do you mean you want to show those rows which name column is not empty?
Gridview can just show the table you query from the DB,so you can change the SQL code to get the right table,
for example:change SELECT * FROM schedule to SELECT * FROM schedule WHERE schedule(name) IS NOT NULL.
actually, I figured it out. I had in that code above the statement
INSERT twice in my program. I removed it and redid my database on my server and fixed the problem. So sorry for the trouble.

C# using DataDirectory in connection string with variable filename

I am new to C# and have been working on a program for work. A simple ticketing program as a backup when the primary goes down. I don't have a server to run a database on so I have been using sqlite. This works great since I don't need to install anything. I would like to set it up to save the database file for each users program to save to a network location with a unique name for the database file. I have figured out how to set the save location of the database but not give the file a name. I would like to use the name of the current logged in user which is already unique and displays when the program runs, it is also added to the database when a new ticket is saved. The program checks the file location and if the database does not exist creates it.
public partial class Ticket_Contingency : Form
{
SQLiteConnection con;
SQLiteDataAdapter da;
SQLiteCommand cmd;
DataSet ds;
DataTable dt;
int id;
string userName = Environment.UserName;
}
public Ticket()
{
InitializeComponent();
AppDomain.CurrentDomain.SetData("DataDirectory", Environment.GetFolderPath(Environment.SpecialFolder.Personal));
private void Form1_Load(object sender, EventArgs e)
{
//loads the saved username from App.config
usernametextBox.Text = userName;
AppDomain.CurrentDomain.SetData("DataDirectory", Properties.Settings.Default.folderdb);
dblabel.Text = Properties.Settings.Default.folderdb;
//Diables Autovalidation
this.AutoValidate = AutoValidate.Disable;
if (!File.Exists("|DataDirectory|incidentdb.sqlite"))
try
{
con = new SQLiteConnection(#"Data Source=|DataDirectory|incidentdb.sqlite;Version=3;New=True;Compress=True;");
con.Open();
cmd = con.CreateCommand();
cmd.CommandText = "CREATE TABLE 'contacts' ('Id' INTEGER PRIMARY KEY NOT NULL DEFAULT (0) ,'firstname' VARCHAR,'lastname' VARCHAR,'mi' CHAR,'email' VARCHAR,'phone' VARCHAR,'ext' CHAR,'visn' CHAR,'site' VARCHAR,'department' VARCHAR,'desklocation' VARCHAR,'notes' VARCHAR,'template' VARCHAR,'priority' CHAR,'summary' VARCHAR, 'status' CHAR, 'timestamp' DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, 'username' VARCHAR)";
cmd.ExecuteNonQuery();
con.Close();
Form1_Load(this, null);
}
catch (SQLiteException ex)
{
// Log the exception
{
}
//Tries to connect to the local Database. Returns error message on failure
try
{
con = new SQLiteConnection(#"Data Source=|DataDirectory|incidentdb.sqlite;Version=3;");
con.Open();
da = new SQLiteDataAdapter("Select ID, firstname as 'firstname', lastname as 'lastname', summary as 'summary', timestamp as 'timestamp' from contacts ORDER by ID ASC", con);
ds = new System.Data.DataSet();
da.Fill(ds, "Person_Details");
dataGridView1.DataSource = ds.Tables[0];
con.Close();
Clear_Form(this, null);
}
catch (SqlException)
{
MessageBox.Show(ex.Message, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
Application.ExitThread();
}
}
}
What I would like to do is replace
if (!File.Exists("|DataDirectory|incidentdb.sqlite"))
with something like
if (!File.Exists("|DataDirectory|" + userName + ".sqlite"))
I know that doesn't work but I really have no idea how to go about this. I have searched everywhere but can only come up with results that look like the original code
if (!File.Exists("|DataDirectory|incidentdb.sqlite")
I would really appreciate some help. Like I said I am new to this. Most of my other issues were solved with research but this is beyond me. Thanks!

Image upload to database

So I managed to set-up a simple test page to upload and store image to my database however I am unsure of whether the storage is successful.
Whenever I store the image into my table under the column Image with the datatype Image, this is what is in the new row <Binary data>. Is this <Binary data> the image?
I was expecting it to display the image in '0' and '1' so I can compare the different items stored. But does having "" stored means that my image had been successfully stored?
My website's logic is coded in c#.
And also I had been trying to find sources with examples to how I may retrieve my image for display.
This is my current insert statement
SqlCommand com = new SqlCommand("insert into ImageTotable "
+ "(myphoto,name) values (#photo, #name)", con);
To retrieve the data will this work?
SqlCommand com2 = new SqlCommand("Select * from ImageTotable WHERE userid ='1'", con);
So if I use a datareader to store the selected items, what can I store my image to so that it will display, a label, image button, etc?
And how do I store the image into the variables? For example if I want to store text I would use:
pw = dr["password"].ToString();**
Therefore for images what would it be like?
EDIT: Full button on click event to handle the image strage
protected void Button1_Click(object sender, EventArgs e)
{
SqlConnection con = new SqlConnection(#"Data Source=*;Initial Catalog=*;Integrated Security=True");
if (!FileUpload1.HasFile)
{
Label1.Visible = true;
Label1.Text = "Please Select Image File"; //checking if file uploader has no file selected
}
else
{
int length = FileUpload1.PostedFile.ContentLength;
byte[] pic = new byte[length];
FileUpload1.PostedFile.InputStream.Read(pic, 0, length);
try
{
con.Open();
SqlCommand com = new SqlCommand("insert into ImageTotable "
+ "(myphoto,name) values (#photo, #name)", con);
com.Parameters.AddWithValue("#photo", pic);
com.Parameters.AddWithValue("#name", TextBox1.Text);
com.ExecuteNonQuery();
Label1.Visible = true;
Label1.Text = "Image Uploaded Sucessfully"; //after Sucessfully uploaded image
}
finally
{
con.Close();
}
}
}
First, the Image type in Db maps to Byte[] in C#, so you should convert your image into Byte[] before inserting into your database. For retrieving your image from the database, you can use the code:
MemoryStream stream = new MemoryStream(Byte[]);// you can read the image by dataadapter or datareader
System.Drawing.Image img = System.Drawing.Image.FromStream(stream);
Here is a good link: http://www.aspdotnet-suresh.com/2011/01/how-to-insert-images-into-database-and.html and hope it can help you.
here is a complete tutorials.
http://freakzmenia.blogspot.com/2010/11/image-saveretrieve-c-web-sql-server.html
http://freakzmenia.blogspot.com/2010/10/image-saveretrieve-c-windows-form-sql.html
This always helps me. 'fileupload' is the File Upload Control Name.
protected void Upload_btn(object sender, EventArgs e)
{
if (fileupload.HasFile)
{
if (fileupload.PostedFile.FileName == "")
{}
else
{
try
{
int filesize = fileupload.PostedFile.ContentLength;
if (filesize > 819200)
{Label1.Text = "File Size Should be Less than 800Kb";
}
else
{string serverFileName = Path.GetFileName(fileupload.PostedFile.FileName);
byte[] documentBinary = new byte[filesize];
fileupload.PostedFile.InputStream.Read(documentBinary, 0, filesize);
string mainquery = "";
mainquery = "insert into table(DocName,DocSize,Data,ContentType) values(#DocName,#DocSize,#Data,#ContentType)";
con.Open();
SqlCommand files_insert_cmd = new SqlCommand(mainquery,con);
files_insert_cmd.Parameters.AddWithValue("#DocName", serverFileName);
files_insert_cmd.Parameters.AddWithValue("#DocSize",fileupload.PostedFile.ContentLength);
files_insert_cmd.Parameters.AddWithValue("#Data", documentBinary);
files_insert_cmd.Parameters.AddWithValue("#ContentType",fileupload.PostedFile.ContentType);
files_insert_cmd.ExecuteNonQuery();
con.Close();
}
}
catch (Exception e1)
{
Label1.Text = e1.ToString();
Label1.Visible = true;
}
}
}
}
Sorry in advance, because i am about to ask a stupid question. How are you checking data in table? are you right clicking on table and selecting edit top 200 rows
If you do like this, it will always show you as < binary Data > where as if you run sql query you can see actual characters in varbinary(max) column or Image column

Categories