Upload and download files on SQL Server from a C# application - c#

I have a C# application that is uploading files to a sql server, I use this code to get the pdf file and then I change it to "bytes" for upload on the SQL Server database.
private void mButtonAddCV_Click(object sender, EventArgs e)
{
openFileDialog1.Filter = "PDF Files | *.pdf";
if (openFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
if (openFileDialog1.FileName.Length > 0)
{
pathCV = openFileDialog1.FileName;
}
}
// Read the file and convert it to Byte Array
string filePath = pathCV;
string contenttype = String.Empty;
contenttype = "application/pdf";
if (contenttype != String.Empty)
{
Stream fs = File.OpenRead(filePath);
BinaryReader br = new BinaryReader(fs);
bytes = br.ReadBytes((Int32)fs.Length);
}
}
I use the code below to upload the file:
if (!mConnector.Update("INSERT INTO **** (***, ***, CV) " +
"VALUES ('" + *** + "', '" + *** + "', '" + bytes + "')"))
{
Messages.errorMessageBox("This CV already exists.");
}
else
{
ChangeScreen(ActiveScreen, ActiveScreens.ActiveScreen_CVList);
}
But now I don't know how to download this file and how to make a pdf file with the data stored on the database to see it. Can anyone help me?
Thanks!

First off, let's change the way you are forming your insert statement so you aren't opening up your system to sql injection. This will also make the insert statement easier to work with
var command = new SqlCommand("INSERT INTO myTable (x, y, z) VALUES (#a, #b, #c)", sqlConnection);
command.Parameters.Add(new SqlParameter("#a", bytes));
command.Parameters.Add(new SqlParameter("#b", bValue));
command.Parameters.Add(new SqlParameter("#c", bValue));
var resultingRows = command.ExecuteNonQuery();
To read the data out, use ExecuteReader, then the File object to save it to the disk.
var command = new SqlCommand("Select a from myTable", sqlConnection);
var reader = command.ExecuteReader();
reader.Read();
var pdfBinaryBuffer = (byte[])reader[0];
// Save file to disk
var file = File.Create("myFile.pdf", pdfBinaryBuffer.Length);
file.Write(pdfBinaryBuffer, 0, pdfBinaryBuffer.Length);
file.Close();

I suggest you to insert your byte data using SqlParameters...
see Inserting a byte array into sql server
Then, read the record using SqlDataReader's GetBytes(...) function see here.

I suggest you to upload pdf and save it in separate folder. you can save the path in database table that I think it is good.
Here is code for file upload
Drag “Fileupload” control to .aspx page (Use this code is for save .PDF to folder)
protected void fileUpload()
{
if (fileUp.HasFile)
{
fileUp.SaveAs(Server.MapPath("~/PoPDF/" + this.txtCusPo.Text +".PDF"));
string imgPrintPo = this.txtCusPo.Text + ".PDF";
}
}
Here is code for file download
You can put this code in button event but here I have used GridView row command event.
protected void gridview_RowCommand(object sender, GridViewCommandEventArgs e)
{
GridViewRow row = (GridViewRow)(((LinkButton)e.CommandSource).NamingContainer);
if (e.CommandName == "SelectDownload")
{
Response.Clear();
Response.ContentType = "application/octet-stream";
Response.AppendHeader("Content-Disposition", "filename=" + e.CommandArgument);
Response.TransmitFile(Server.MapPath("~/PoPDF/") + e.CommandArgument);
//Response.Flush();
Response.End();
}
}

Related

Why won't my code upload a file to the specified folder on the web server when using the fileupload control?

Good afternoon. I have an asp.net web forms application using c#. I am having some difficulty getting my code to work properly. The data is uploaded successfully to the sql server database, but the file isn't saved to the specified "Data" folder. any help would be greatly appreciated?
The ID of the fileupload control is "fu_doc_upld". I don't get any errors when using the form, the files just aren't saving to the "Data" folder (or any other folder). Here is the code behind that I'm using:
protected void btn_frm_new_doc_save_close_Click(object sender, EventArgs e)
{
int i = 0;
string filename = fu_doc_upld.FileName;
if (fu_doc_upld.HasFile)
{
while (System.IO.File.Exists(Server.MapPath("~/Data/") + filename))
{
i++;
filename = fu_doc_upld.FileName + " (" + i.ToString() + ")";
fu_doc_upld.PostedFile.SaveAs(Server.MapPath("~/Data/") + filename);
}
}
hdn_filename_txt.Value = (Server.MapPath("~/Data/") + filename);
hdn_doc_uplod_dt_txt.Value = DateTime.Now.ToString();
SqlConnection idrf_cnxn = new SqlConnection("Data Source=WDBSVCPRD01\\SVCDB;Initial Catalog=idrf;Integrated Security=True");
{
SqlCommand new_doc_cmd = new SqlCommand("Insert Into tbl_doc(doc_title, doc_type_list, doc_org_list, doc_dept_list, doc_desc, prior_contract_cd, legal_comp_contract_id, doc_upld_dt, doc_path, vendor_id_fk) Values(LTRIM(RTRIM(#doc_title)), LTRIM(RTRIM(#doc_type_list)), LTRIM(RTRIM(#doc_org_list)), LTRIM(RTRIM(#doc_dept_list)), LTRIM(RTRIM(#doc_desc)), LTRIM(RTRIM(#prior_contract_cd)), LTRIM(RTRIM(#legal_comp_contract_id)), LTRIM(RTRIM(#doc_upld_dt)), LTRIM(RTRIM(#doc_path)), LTRIM(RTRIM(#vendor_id_fk)))", idrf_cnxn);
new_doc_cmd.Parameters.AddWithValue("#doc_title", doc_title_txt.Text);
new_doc_cmd.Parameters.AddWithValue("#doc_type_list", doc_type_ddl.Text);
new_doc_cmd.Parameters.AddWithValue("#doc_org_list", doc_org_ddl.Text);
new_doc_cmd.Parameters.AddWithValue("#doc_dept_list", doc_dept_ddl.Text);
new_doc_cmd.Parameters.AddWithValue("#doc_desc", doc_desc_txt.Text);
new_doc_cmd.Parameters.AddWithValue("#prior_contract_cd", prior_contract_cd_txt.Text);
new_doc_cmd.Parameters.AddWithValue("#legal_comp_contract_id", lgl_comp_cont_id_txt.Text);
new_doc_cmd.Parameters.AddWithValue("#doc_upld_dt", hdn_doc_uplod_dt_txt.Value);
new_doc_cmd.Parameters.AddWithValue("#doc_path", hdn_filename_txt.Value);
new_doc_cmd.Parameters.AddWithValue("#vendor_id_fk", hdn_vendor_id_txt.Value);
idrf_cnxn.Open();
new_doc_cmd.ExecuteNonQuery();
idrf_cnxn.Close();
if (IsPostBack)
{
Response.Redirect("~/Default.aspx");
}
}
}
Any help would be greatly appreciated.
Thanks,
J
You only call SaveAs() when the file exists. You could've found this by placing a breakpoint and stepping through your code.
Move the save out of the loop:
string filename = fu_doc_upld.FileName;
while (System.IO.File.Exists(Server.MapPath("~/Data/") + filename))
{
i++;
filename = fu_doc_upld.FileName + " (" + i.ToString() + ")";
}
fu_doc_upld.PostedFile.SaveAs(Server.MapPath("~/Data/") + filename);
Note that this code will remove the extension if a file already exists. See C#: How would you make a unique filename by adding a number? for a better implementation.

Download multiple files in same record from a database table

I have this table to store Purchase Order data, it can hold up to 3 files (first file is required, second and third is optional) which their column names are highlighted in the picture.
I have already done the Upload page, which save all the data entered and uploaded by user to the database, it is working fine, I can see all the saved file names and bytes in the table.
I am working on the View page, which retrieve data from database and display it to the webpage and have problem of retrieving the files.
The idea is to display the file name to the page (which is working fine) and when user click onto the file name, they can save it to the computer (or open/run etc depend on web browser prompt windows), problem here is that: I can only save the first file, when clicking on the second and third file name, nothing happened although when in debugging mode they (name, type and data of file2 and file3) do exist but the prompt windows to save file is not appeared
Any idea how to fix this or if anyone have better method of how to download these files please help.
Here is my code (please ignore the unrelated codes or please let me know if you want to know what they do):
The View.aspx to display file names
<asp:LinkButton ID="lbtPOFile" runat="server" OnClick="lbtPOFile_Click"></asp:LinkButton>
<asp:LinkButton ID="lbtPOFile2" runat="server" OnClick="lbtPOFile2_Click"></asp:LinkButton>
<asp:LinkButton ID="lbtPOFile3" runat="server" OnClick="lbtPOFile3_Click"></asp:LinkButton>
C# behind: the DownloadFile() method has 3 parameters, they are just column names in the database table, corresponding to the file1, file2 or file3, it supposes to retrieve the file when user click onto the file name (called in the click events below)
protected void DownloadFile(string fileNameColumn, string fileTypeColumn, string fileDataColumn)
{
string guid = !string.IsNullOrEmpty(Request.QueryString["guid"]) ? Request.QueryString["guid"] : Guid.Empty.ToString();
string id = !string.IsNullOrEmpty(Request.QueryString["id"]) ? Request.QueryString["id"] : "0";
if (requestDAL.ValidatePODetailLink(guid, Convert.ToInt32(id)))
{
byte[] bytes = null;
string fileName = "";
string contentType = "";
DataTable PODetail = requestDAL.GetPODetail(guid, Convert.ToInt32(id));
foreach (DataRow row in PODetail.Rows)
{
bytes = (byte[])row[fileDataColumn];
contentType = row[fileTypeColumn].ToString();
fileName = row[fileNameColumn].ToString();
}
Response.Clear();
Response.Buffer = true;
Response.Charset = "";
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.ContentType = contentType;
Response.AppendHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
Response.BinaryWrite(bytes);
Response.Flush();
Response.End();
}
else
{
//Display message
InfoPanel.Visible = true;
lblMessage.Text = "<b>Invalid file or an error has occurred while connecting to the database. Please try again later!</b>";
lblMessage.CssClass = "text text-danger bold";
InfoPanel.CssClass = "panel panel-danger";
FormPanel.Visible = false;
FormPanel.Enabled = false;
}
}
protected void lbtPOFile_Click(object sender, EventArgs e)
{
try
{
DownloadFile("poFileName", "poFileContentType", "poFileData");
}
catch (Exception ex)
{
//Display message
InfoPanel.Visible = true;
lblMessage.Text = "<b>An error has occurred. Please try again later!</b></br>" + ex.Message;
lblMessage.CssClass = "text text-danger bold";
InfoPanel.CssClass = "panel panel-danger";
FormPanel.Visible = false;
FormPanel.Enabled = false;
}
}
protected void lbtPOFile2_Click(object sender, EventArgs e)
{
try
{
DownloadFile("poFileName2", "poFileContentType2", "poFileData2");
}
catch (Exception ex)
{
//Display message
InfoPanel.Visible = true;
lblMessage.Text = "<b>An error has occurred. Please try again later!</b></br>" + ex.Message;
lblMessage.CssClass = "text text-danger bold";
InfoPanel.CssClass = "panel panel-danger";
FormPanel.Visible = false;
FormPanel.Enabled = false;
}
}
protected void lbtPOFile3_Click(object sender, EventArgs e)
{
try
{
DownloadFile("poFileName3", "poFileContentType3", "poFileData3");
}
catch (Exception ex)
{
//Display message
InfoPanel.Visible = true;
lblMessage.Text = "<b>An error has occurred. Please try again later!</b></br>" + ex.Message;
lblMessage.CssClass = "text text-danger bold";
InfoPanel.CssClass = "panel panel-danger";
FormPanel.Visible = false;
FormPanel.Enabled = false;
}
}
Some related functions in case you need it:
// Validate link for employee (link format is View.aspx?guid=xxx&id=xxx)
public static bool ValidatePODetailLink(string guid, int poID)
{
using (SqlConnection con = new SqlConnection(CS))
{
string query = "SELECT COUNT(*) FROM PO WHERE poID = #poID AND poGUID = #guid";
SqlCommand cmd = new SqlCommand(query, con);
cmd.Parameters.AddWithValue("#guid", guid);
cmd.Parameters.AddWithValue("#poID", poID);
con.Open();
int i = Convert.ToInt32(cmd.ExecuteScalar());
if (i == 1) return true;
else return false;
}
}
//Get po request details for employee
public static DataTable GetPODetail(string guid, int poID)
{
using (SqlConnection con = new SqlConnection(CS))
{
string query = "SELECT * FROM PO WHERE poID = #poID AND poGUID = #guid";
SqlCommand cmd = new SqlCommand(query, con);
cmd.Parameters.AddWithValue("#guid", guid);
cmd.Parameters.AddWithValue("#poID", poID);
con.Open();
SqlDataAdapter da = new SqlDataAdapter(cmd);
DataTable dt = new DataTable();
da.Fill(dt);
return dt;
}
}
PROBLEM FOUND:
I use UpdatePanel and only put <Triggers> <asp:PostBackTrigger ControlID="lbtPOFile" /> </Triggers> hence it was missing PostBackTrigger for lbtPOFile2 and lbtPOFile3. Added those 2 lines and it works.
I would suggest the following approach.
Revert your code to the "known good" state (where it can only handle the download of one file, but does so correctly)
Refactor this code so that it still supports a single file download. Take the code that streams the file contents into the response; move it into a separate function (perhaps call this SendFile); call that function from your click handler; recompile and confirm that everything is still working.
Now modify SendFile so that it accepts input parameters that determine whether it will return file 1, file 2, or file 3. Modify the click handler so that it passes the parameters that indicate file 1. Recompile and test again, make sure it still works.
Now add two additional click handlers for your other two link buttons. Should be identical to your existing click handler except for the arguments that are passed to SendFile. Recompile and test with all three files.

I want to show file upload progress in c# application

I want to show a file upload progress in c# windows application As I am using online database it takes a bit more time to save or upload.I am using following Code.I have searched but It does not shows exact percent wise progress.Also I Want to change file name before moving to another lOcation.
Thanks In advance.
OpenFileDialog dlg = new OpenFileDialog();
DialogResult dlgRes = dlg.ShowDialog();
Application.DoEvents();
label14.Visible = true;
if (DialogResult.OK != DialogResult.Cancel)
{
foreach (string file in dlg.FileNames)
{
try
{
newpath = Path.Combine(textBox2.Text, Path.GetFileName(file)).ToString();
filenametemp = "tush" + Path.GetFileName(file).ToString();
if (String.IsNullOrEmpty(textBox2.Text))
{
MessageBox.Show("please select folder to save");
}
else
{
File.Copy(file, Path.Combine(textBox2.Text, Path.GetFileName(file)).ToString());
if (dlgRes != DialogResult.Cancel)
{
//Provide file path in txtFilePath text box.
txtFilePath.Text = dlg.FileName;
}
//string folderpath = System.IO.Directory.GetParent(Environment.CurrentDirectory).Parent.FullName + textBox2.Text;
//string filePath = textBox2.Text + System.IO.Path.GetFileName(dlg.FileName);
//System.IO.File.Copy(dlg.FileName, folderpath, true);
try
{
//Read File Bytes into a byte array
byte[] FileData = ReadFile(txtFilePath.Text);
//Initialize SQL Server Connection
SqlConnection CN = new SqlConnection(ConfigurationManager.ConnectionStrings["Copymanagment"].ConnectionString);
//Set insert query
string qry = "insert into fileinfo (File_Id,File_Path,date,OriginalPath,Billnumber,Billdate,FileData) values(#FileId,#Filepath,#Date,#OriginalPath,#Billnumber,#Billdate,#FileData)";
//Initialize SqlCommand object for insert.
SqlCommand SqlCom = new SqlCommand(qry, CN);
string path = textBox2.Text;
string[] arrpath = null;
int count;
arrpath = path.Split('\\');
for (count = 0; count <= arrpath.Length - 1; count++)
{
// MessageBox.Show(arrpath[count]);
}
string folder = arrpath[arrpath.Length - 1] + databaseid().ToString();
//We are passing Original File Path and File byte data as sql parameters.
string fileid = Path.GetDirectoryName(dlg.FileName);
SqlCom.Parameters.Add(new SqlParameter("#FileId", (object)folder));
SqlCom.Parameters.Add(new SqlParameter("#Filepath", (object)newpath));
SqlCom.Parameters.Add(new SqlParameter("#Date", (object)System.DateTime.Now.ToString("dd-MM-yyyy hh:mm:ss tt")));
SqlCom.Parameters.Add(new SqlParameter("#OriginalPath", (object)txtFilePath.Text));
SqlCom.Parameters.Add(new SqlParameter("#Billnumber", (object)textbillno.Text));
SqlCom.Parameters.Add(new SqlParameter("#Billdate", (object)dateTimePicker1.Value.ToString("dd-MM-yyyy")));
SqlCom.Parameters.Add(new SqlParameter("#FileData", (object)FileData));
//Open connection and execute insert query.
CN.Open();
SqlCom.ExecuteNonQuery();
CN.Close();
label14.Visible = false;
//Close form and return to list or Files.
MessageBox.Show("File saved Succsesfully");
txtFilePath.Text = "";
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
}
catch
{
MessageBox.Show("File already available");
}
}
}
The way you have it done, a single statement in inserting the whole data in one shot and blocks until done without a chance to update tge UI. You can upload your BLOB data in chuncks using UPDATETEXT. see https://msdn.microsoft.com/en-us/library/vstudio/3517w44b(v=vs.100).aspx for full explanations on how to do that. Doing that, you will have the opportunity to update the value of a prigress bar.
You can use asp.net ajax control toolkit. There is a ajax file upload control.
Note Do not get confused with asynFile upload control in the same library(that control does not have progress bar).
You can get info here http://www.codingfusion.com/Post/AjaxFileUpload-example-to-upload-multiple-files-in
To download the library go here http://www.codingfusion.com/Post/3-Different-ways-to-add-AjaxControlToolkit-in-Asp
for windows app try following https://stackoverflow.com/a/9446524/4810628

How to store video files in SQL database using asp.net? [duplicate]

I have scenario where i want to store video into database and show in grid to download from database ,i will upload video by fileupload control and it should be sql server2008 database,which is best way in c# and asp.net?
There are many link for it. Check out this.
http://weblogs.asp.net/hajan/archive/2010/06/21/save-and-display-youtube-video-links-on-asp-net-website.aspx
http://forums.asp.net/t/1104451.aspx/1?How+to+retrieve+video+file+from+sql+server+database
http://www.saurabhdeveloper.com/techtips_details.php?tipsid=15
http://forums.asp.net/p/1533758/3719583.aspx
http://forums.asp.net/t/1045855.aspx/2/10
http://forums.asp.net/t/1511588.aspx/1
http://www.dotnetspider.com/forum/274821-Play-video-file-asp-net-page.aspx
http://blogs.ugidotnet.org/kfra/archive/2006/10/04/50003.aspx
http://www.dotnetspider.com/resources/16239-code-for-video-upload.aspx
http://www.c-sharpcorner.com/Forums/Thread/88899/
http://www.asp.net/webmatrix/tutorials/10-working-with-video
http://www.c-sharpcorner.com/Forums/Thread/88899/
Try this code
byte[] buffer;
//this is the array of bytes which will hold the data (file)
SqlConnection connection;
protected void ButtonUpload_Click(object sender, EventArgs e)
{
//check the file
if (FileUpload1.HasFile && FileUpload1.PostedFile != null
&& FileUpload1.PostedFile.FileName != "")
{
HttpPostedFile file = FileUpload1.PostedFile;
//retrieve the HttpPostedFile object
buffer = new byte[file.ContentLength];
int bytesReaded = file.InputStream.Read(buffer, 0,
FileUpload1.PostedFile.ContentLength);
if (bytesReaded > 0)
{
try
{
string connectionString =
ConfigurationManager.ConnectionStrings[
"uploadConnectionString"].ConnectionString;
connection = new SqlConnection(connectionString);
SqlCommand cmd = new SqlCommand
("INSERT INTO Videos (Video, Video_Name, Video_Size)" +
" VALUES (#video, #videoName, #videoSize)", connection);
cmd.Parameters.Add("#video",
SqlDbType.VarBinary, buffer.Length).Value = buffer;
cmd.Parameters.Add("#videoName",
SqlDbType.NVarChar).Value = FileUpload1.FileName;
cmd.Parameters.Add("#videoSize",
SqlDbType.BigInt).Value = file.ContentLength;
using (connection)
{
connection.Open();
int i = cmd.ExecuteNonQuery();
Label1.Text = "uploaded, " + i.ToString() + " rows affected";
}
}
catch (Exception ex)
{
Label1.Text = ex.Message.ToString();
}
}
}
else
{
Label1.Text = "Choose a valid video file";
}
}
You say it "should" be SQL Server 2008, but does it have to be?
If not, SQL Server 2012 offers File Tables that are designed for storing large files in SQL Server. It actually stores the data on the filesystem but in a way that you don't have to write any code to manage the actual file.
If it does need to be SQL Server 2008 then you have the following options:
1) FileStream using a varbinary(MAX) column type - there can be performance issues with this method. I personally would not store video in this way.
2) Put the file on the file system (on disk) and only store the filepath/filename in the DB. You then write code to manage CRUD operations on the file system.
It will help you... see the following link http://www.codeproject.com/Articles/308552/Upload-and-Download-Files-to-SQL-Servers-in-ASP-Ne

Try to open twice a document, only on server, with office documents

I got an issue with my aspx page, that open one document.
The problem is when I click on open, of the dialog box open, it will open the document, and the same document a second time in read only.
And this happened only when i run my silverlight application on a server, not localhost.
THe code calling the aspx(silverlight page behind code) :
ub = (new Uri(HtmlPage.Document.DocumentUri, "ViewDocument.aspx?&connexion=" + connexion + ";&id=" + id.ToString()));
if (HtmlPage.IsPopupWindowAllowed)
{
HtmlPopupWindowOptions opt = new HtmlPopupWindowOptions();
HtmlPage.PopupWindow(ub, "file", opt);
}
else
{
HtmlPage.Window.Navigate(ub);
}
HtmlPage.Window.Navigate(ub);
And the aspx page :
OracleConnection conn = new OracleConnection(vChaineConnexion);
conn.Open();
string v_requete = "";
if (id != null)
{
v_requete = "SELECT doc, extension " +
"FROM t_doc " +
"WHERE id= "+ id.ToString();
}
//si la requête n'est pas vide
if (!String.IsNullOrEmpty(v_requete))
{
OracleCommand cmd = new OracleCommand(v_requete, conn);
OracleDataAdapter da = new OracleDataAdapter(cmd);
OracleCommandBuilder ocb = new OracleCommandBuilder(da);
DataSet dataset = new DataSet();
if (id != null)
{
da.Fill(dataset, "Extension");
}
//retrieving binary data of pdf from dataset to byte array
byte[] blob = (byte[])dataset.Tables[0].Rows[0].ItemArray[0];
string extension = dataset.Tables[0].Rows[0].ItemArray[1].ToString();
HttpContext.Current.Response.Buffer = true;
HttpContext.Current.Response.ClearContent();
HttpContext.Current.Response.ClearHeaders();
if(extension.equals(".doc"))
{
HttpContext.Current.Response.ContentType = "application/msword";
}
if (id != null)
{
HttpContext.Current.Response.AddHeader("content-disposition", "Attachment; filename=" + id.ToString() + extension);
}
HttpContext.Current.Response.AddHeader("content-length", blob.Length.ToString());
HttpContext.Current.Response.BinaryWrite(blob);
if (HttpContext.Current.Response.IsClientConnected)
{
HttpContext.Current.Response.Flush();
HttpContext.Current.ApplicationInstance.CompleteRequest(); //instead of Response.End()
//HttpContext.Current.Response.End();
}
}
I don't understand, why it tried to open the document two times, only on servers, while it works fine on localhost.
I go through my method, calling the aspx only one time, and at the moment I click open on the popupWindow, it open twice the document.
And it seems, this happened with word, but not with a pdf..
Correction : all office documents... (office 2010 on my desk)
See a error message quickly : online services smartscreen unavailable
I think this is the probleme but I don't understant why.
Why?

Categories

Resources