I am using C#. I want to store PDF files from a Windows forms application to a SQL database. And I want to retrieve it to my Windows Forms application again. What controls can I use to upload PDF files (for example for image I use picture box). What is the data type for PDF files?
Thanks in advance
To select a file you can use OpenFileDialog
Saving any file into database
You'd better store pdf in file storage and save link to it in database.
To store a PDF file in your SQL Server Database, you need to store the contents of the file in BinaryData field. However, I am sure that you will face so many problem with this setup, that you would do better to save your file contents in the SystemData folder and just store the file path or name in to DB.
This will be much more reliable and easy to maintain.
Another approach if your application is storing only files, is to use MongoDb instead of SQL Server. I am not familiar with that, but quite sure that this will be an easy and good solution.
There is an app in the Windows App Store specifically for storing PDF file info and PDF metadata in a SQL database.
You can then search and filter that database using simple, standard SQL queries.
https://www.microsoft.com/en-us/store/p/pdfdb/9n4z1l2hc2c0
public void getTestReportDocument(string reportid, string extenstype)
{
try
{
string filesName = "";
if (sqlConn.State == ConnectionState.Closed)
sqlConn.Open();
if(extenstype == ".pdf")
{
filesName = Path.GetTempFileName();
}
else
{
filesName = Path.GetTempFileName() + extenstype;
}
SqlCommand cmd = new SqlCommand("GetTestReportDocuments", sqlConn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#ReportID", reportid);
using (SqlDataReader dr = cmd.ExecuteReader(System.Data.CommandBehavior.Default))
{
while (dr.Read())
{
int size = 1024 * 1024;
byte[] buffer = new byte[size];
int readBytes = 0;
int index = 0;
using (FileStream fs = new FileStream(filesName, FileMode.Create, FileAccess.Write, FileShare.None))
{
while ((readBytes = (int)dr.GetBytes(0, index, buffer, 0, size)) > 0)
{
fs.Write(buffer, 0, readBytes);
index += readBytes;
}
}
}
}
Process prc = new Process();
prc.StartInfo.FileName = filesName;
prc.Start();
}
catch (Exception ex)
{
throw ex;
}
finally
{
//daDiagnosis.Dispose();
//daDiagnosis = null;
}
}
Take a look at this screenshot for the solution.
Related
We are trying to store an executable(exe) file in SQL. We are getting no error either writing or reading. Just the file we stored is not working after downloading back.
This is how we store the file:
databaseFilePut(#"FilePath", con, dt.Rows[0].ItemArray[0].ToString(), "ASIL");
And this is the inside of the function:
public static void databaseFilePut(string varFilePath, SqlConnection con, string version, string OFSET )
{
byte[] file;
using (var stream = new FileStream(varFilePath, FileMode.Open, FileAccess.Read))
{
using (var reader = new BinaryReader(stream))
{
file = reader.ReadBytes((int)stream.Length);
}
}
using (var sqlWrite = new SqlCommand("UPDATE ERP_TOOL_UPDATE SET Version=#Version1, ExeDosyasi= #ExeDosyasi1, OFSET= #OFSET1", con))
{
sqlWrite.Parameters.AddWithValue("#Version1", (double.Parse(version) + 1).ToString());
sqlWrite.Parameters.Add("#ExeDosyasi1", SqlDbType.VarBinary, file.Length).Value = file;
sqlWrite.Parameters.AddWithValue("#OFSET1", "ASIL");
sqlWrite.ExecuteNonQuery();
}
}
After saving to the database this is what the data like:
0x4D5A90000300000004000000FFFF0000B8000.... and goes on.
After reading we try to recreate the stored exe with this code:
SqlCommand com = new SqlCommand("Select ExeDosyasi From ERP_TOOL_UPDATE WHERE OFSET = 'ASIL' ", con);
com.CommandType = CommandType.Text;
SqlDataReader reader = com.ExecuteReader();
reader.Read();
byte[] blob;
byte[] blob2;
blob = (byte[])reader[0];
blob2 = System.Text.Encoding.Default.GetBytes(System.Text.Encoding.Unicode.GetString(blob));
using (var fs = new FileStream(#"C:\Users\Bilal\Desktop\ERPAnalizTool.exe", FileMode.Create, FileAccess.Write))
{
fs.Write(blob2, 0, blob2.Length);
fs.Flush();
}
We are not getting any errors, it saves the file. Just the problem is the file has a little bit smaller size. When we try to run, it doesn't run. Like it never was an exe before.
Any help would be appreciated. Thank you all.
Your problem is the following line:
blob2 = System.Text.Encoding.Default.GetBytes(System.Text.Encoding.Unicode.GetString(blob));
The blob variable contains the bytes you wrote to the database, which is the content of the file read in the databaseFilePut method. There is no reason at all to convert it to a Unicode string and then to the system default encoding (Windows-1252 on my system). The data is not a string, it is binary. The double conversion will simply produce a mangled byte sequence.
Simply write the blob variable to disk:
blob = (byte[])reader[0];
File.WriteAllBytes(#"C:\Users\Bilal\Desktop\ERPAnalizTool.exe", blob);
i have created simple project save blob file data into oracle database using c# winform and worked fine. Now, i wanna play video from blob oracle data using c# but i couldn't. here is my code:
if (koneksidb.con.State == ConnectionState.Open)
{
koneksidb.con.Close();
}
koneksidb.con.Open();
OracleCommand cmd = new OracleCommand();
OracleDataReader dr;
cmd.CommandText = #"SELECT ID,FILENAME, FILEDATA, KETERANGAN, SUBSTR(FILENAME, -4)AS FILEEXTENTION FROM LATIHANFILEMANAGER WHERE ID = '1' AND ISPREVIEW = N'1'";
cmd.Connection = koneksidb.con;
dr = cmd.ExecuteReader();
while (dr.Read())
{
string fileExtention = dr["FILEEXTENTION"].ToString(); //got file extention from database
switch(fileExtention)
{
case ".pdf": //when blob is pdf file worked fine
byte[] FileBytes = (byte[])dr["FILEDATA"];
System.IO.MemoryStream stream = new System.IO.MemoryStream(FileBytes);
fmPdfViewer f = new fmPdfViewer();
f.pdfViewer1.LoadDocument(stream); //when file .pdf i can display preview using pdf viewer in devexpress
f.Show();
break;
case ".mp4": //when blob is video
string path = ""; //here the problem how can i play file video from blob oracle data
fmVideoViewer vd = new fmVideoViewer();
vd.axWindowsMediaPlayer1.URL = path;
vd.axWindowsMediaPlayer1.settings.autoStart = true;
vd.Show();
break;
}
}
dr.Close();
really need the solution, thanks before.
You can save the file on disk and play it.
byte[] bytes = (byte[])dr["FILEDATA"];
string name = (string)dr["FILENAME"] + (string)dr["FILEEXTENTION"];
var path = System.IO.Path.Combine(Application.StartupPath, name);
System.IO.File.WriteAllBytes(path , bytes);
this.axWindowsMediaPlayer1.URL = path;
this.axWindowsMediaPlayer1.Ctlcontrols.play();
You can use Application.StartupPath or any other path you prefer to cache files.
After a while it's better to cleanup cached files.
I am using dotnet zip library to create zip file. My files are saved into a database and I am reading each row and load file data into memory from the database and save the memory stream to zip file. my below code works fine.
using System.IO;
using Ionic.Zip;
private void button2_Click(object sender, EventArgs e)
{
using (SqlConnection sqlConn = new SqlConnection(#"Data Source=BBATRIDIP\SQLSERVER2008R2;Initial Catalog=test;Integrated Security=True"))
{
string query = String.Format(#"SELECT Name, ContentType, Data FROM [TestTable]");
SqlCommand cmd = new SqlCommand(query, sqlConn);
cmd.Connection.Open();
System.IO.MemoryStream memStream = null;
ZipFile zip = new ZipFile();
zip.MaxOutputSegmentSize = 1024 * 1024; // 1MB each segment size would be
// the above line would split zip file into multiple files and each file
//size would be 1MB
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
byte[] data = (byte[])reader["Data"];
memStream = new System.IO.MemoryStream(data);
string strFile = reader["Name"].ToString() + "\\" + reader["ContentType"].ToString();
ZipEntry ze = zip.AddEntry(strFile, memStream);
int xx = 0;
}
}
zip.Save(#"e:\MyCustomZip.zip");
memStream.Dispose();
MessageBox.Show("Job Done");
// here u can save the zip in memory stream also there is a overload insteaa of saving in HD
}
}
but if i change a bit into the code then corrupted zip file is creating. if i change this line zip.Save(#"e:\MyCustomZip.zip"); then problem occur.
using (SqlConnection sqlConn = new SqlConnection(#"Data Source=BBATRIDIP\SQLSERVER2008R2;Initial Catalog=test;Integrated Security=True"))
{
string query = String.Format(#"SELECT Name, ContentType, Data FROM [TestTable]");
SqlCommand cmd = new SqlCommand(query, sqlConn);
cmd.Connection.Open();
System.IO.MemoryStream memStream = null;
ZipFile zip = new ZipFile();
zip.MaxOutputSegmentSize = 1024 * 1024; // 1MB each segment size would be
// the above line would split zip file into multiple files and each file
//size would be 1MB
zip.Save(#"e:\MyCustomZip.zip");
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
byte[] data = (byte[])reader["Data"];
memStream = new System.IO.MemoryStream(data);
string strFile = reader["Name"].ToString() + "\\" + reader["ContentType"].ToString();
ZipEntry ze = zip.AddEntry(strFile, memStream);
int xx = 0;
}
}
memStream.Dispose();
MessageBox.Show("Job Done");
// here u can save the zip in memory stream also there is a overload insteaa of saving in HD
}
I want to create zip with zero kb initially and when I will add stream to zip in loop then zip file size will increase gradually. if you see my above code where I try to do that but I got no success. what am I doing wrong in the code?
Another issue
dotnet zip compression ratio not good. i zip a 152 KB doc file with dotnet zip and when zip was created then i was zip file size was 136KB. is there any tweak exist which create small size zip file. share the knowledge. thanks
So, looking at the documentation for ZipFile.Save, we see the following:
Use this when creating a new zip file, or when updating a zip archive.
So, it seems that you need to call this repeatedly to get the "update" behaviour you are looking for. As such just need to move your Save into the loop:
//...
ZipFile zip = new ZipFile();
zip.MaxOutputSegmentSize = 1024 * 1024;
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
byte[] data = (byte[])reader["Data"];
memStream = new System.IO.MemoryStream(data);
string strFile =
reader["Name"].ToString() + "\\" + reader["ContentType"].ToString();
ZipEntry ze = zip.AddEntry(strFile, memStream);
zip.Save(#"e:\MyCustomZip.zip");
}
}
With regards to your second question (never a good idea on SO, try to stick to one problem per question):
Without knowing what you are compressing, it's very difficult to speculate about what kind of compression ratio you might achieve. If the data is already compressed (e.g. compressed image/video such as jpeg/h264), zipping isn't going to give you any gains whatsoever. Your only hint about the nature of the content is that it is a "doc". If you're talking about a modern Word document (docx), this is already a zip compressed folder structure. Gains will be minimal. If it's another kind of doc, perhaps it contains embedded (compressed) media? This will also be relatively incompressible.
I'm trying to get attachments (images, word documents, etc.) stored as an Image datatype from a SQL Server database. The attachments can be of any file type, but I'm just trying to get a .jpg to download successfully.
I'm able to save the file to my local drive, but it appears to be corrupting the file in the process.
What I'm trying to do:
Retrieve binary data of type IMAGE from SQL Server Database.
Create a file from the binary data.
Save the file to a local directory.
My CODE:
public void ProcessRequest()
{
//Get the ticket number from query string
_ticketNumber = context.Request.QueryString["ID"];
SqlConnection conn = new SqlConnection(_DBConn);
SqlCommand cmd = new SqlCommand();
string fileName = ""; //Holds the file name retrieved from DB
byte[] data; // Holds the IMAGE data from DB
using (conn)
{
using (cmd)
{
cmd.CommandType = CommandType.Text;
cmd.CommandText = #"SELECT File_Name, Data FROM Tickets_All INNER JOIN Attachments ON Tickets_All.ID = Attachments.[Object_ID] WHERE Ticket = #Ticket";
cmd.Parameters.AddWithValue("#Ticket", _ticketNumber);
cmd.Connection = conn;
conn.Open();
SqlDataReader reader = cmd.ExecuteReader();
if (reader.HasRows)
{
while (reader.Read())
{
fileName = reader.GetString(0);
data = (byte[])reader["Data"];
if (data != null)
{
SaveData(fileName, data);
}
}
}
reader.Close();
}
}
protected bool SaveData(string FileName, byte[] Data)
{
string path = #"C:\Windows\temp\test.jpg";
try
{
BinaryWriter writer = new BinaryWriter(File.OpenWrite(path));
writer.Write(Data);
writer.Flush();
writer.Close();
}
catch (Exception ex)
{
return false;
}
return true;
}
Please forgive me if the code isn't up to par with best practices, I'm more of a VB programmer and I've never had to do this before. I'm just trying to get a working example.
Thanks in advance.
I would use the Image.FromStream method to do this :
http://msdn.microsoft.com/en-us/library/system.drawing.image.fromstream(v=vs.110).aspx
protected bool SaveData(string FileName, byte[] Data)
{
using (Image image = Image.FromStream(new MemoryStream(Data)))
{
image.Save("MyImage.jpg", ImageFormat.Jpeg);
}
return true;
}
Thanks for the input everyone. After doing some additional testing, I think that the data being retrieved from the database has been compressed in some way. I'm able to insert and pull out files programmatically just fine, the problem comes in when the application puts the data into the database (3rd party software). I'm going to look into the compression what I can come up with.
I'm trying to load text files (.aspx, .cs, html, etc) into a sql server 2008 database.
I'm able to load all files that are less than 64 kb so far. I have two questions; How do I get around the 64 kb limit, and is the method I'm using the best way to do this?
Thanks for the help.
Database:
file_length int,
file_path varchar(250),
file_string varchar(MAX)
Code:
private static void Load_Files()
{
string source = HttpContext.Current.Server.MapPath("~/website/");
DirectoryInfo di = new DirectoryInfo(source);
FileInfo[] files = di.GetFiles();
foreach (FileInfo f in files)
{
string sourceFile = f.FullName;
FileStream fs_reader = new FileStream(sourceFile, FileMode.Open, FileAccess.Read);
StreamReader reader = new StreamReader(fs_reader);
string content = reader.ReadToEnd();
Int32 file_length = content.Length;
string CS = ConfigurationManager.ConnectionStrings["SQL_CS"].ConnectionString;
SqlConnection SQL_Conn_01 = new SqlConnection(CS);
string SQL_01 = "INSERT INTO Page_File_Store (file_length, file_path, file_string) VALUES (#file_length, #file_path, #file_string)";
SqlCommand SQL_File_Load = new SqlCommand(SQL_01, SQL_Conn_01);
SQL_File_Load.Parameters.Add(new SqlParameter("#file_length", file_length));
SQL_File_Load.Parameters.Add(new SqlParameter("#file_path", sourceFile));
SQL_File_Load.Parameters.Add(new SqlParameter("#file_string", content));
SQL_Conn_01.Open();
SQL_File_Load.ExecuteNonQuery();
SQL_Conn_01.Close();
reader.Close();
}
}
In SQL server 2008, Microsoft added a new data type, called FileStream. It "integrates the SQL Server Database Engine with an NTFS file system by storing varbinary(max) binary large object (BLOB) data as files on the file system". You can read more about FileStream here.
You seem to be doing a lot of extra, unnecessary work - somewhere along the lines, something goes wrong.
I tried your scenario with this code here and it works without a hitch - no problems at all, even for text files over 500 KB in size:
// read the whole text of the file in a single operation
// no filestream, memorystream and other messy stuff needed!
string file_content = File.ReadAllText(sourceFile);
Int32 file_length = content.Length;
// best practice: always put SqlConnection and SqlCommand into using() {..} blocks!
using (SqlConnection _con = new SqlConnection(CS))
{
string _query =
"INSERT INTO Page_File_Store (file_length, file_path, file_string) " +
"VALUES (#file_length, #file_path, #file_string)";
using(SqlCommand _cmd = new SqlCommand(_query, _con))
{
// just add the three parameters with their values
// ADO.NET figures out the rest (datatypes etc.) by itself!
_cmd.Parameters.AddWithValue("#file_length", file_length);
_cmd.Parameters.AddWithValue("#file_path", fileName);
_cmd.Parameters.AddWithValue("#file_string", content);
_con.Open();
_cmd.ExecuteNonQuery();
_con.Close();
}
}
That should definitely work - try it!
Marc
Does it solve your problem if you replace this:
SQL_File_Load.Parameters.Add(new SqlParameter("#file_string", content));
With this:
SqlParameter contentParameter = new SqlParameter("#file_string", SqlDbType.NVarChar, -1);
contentParameter.Value = content;
SQL_File_Load.Parameters.Add(contentParameter);
The -1 is interpretted as (MAX)