Retrieving Compressed files from database - c#

I have a SQL Server 2008-R2 database that has a table that is storing different types of files (Word Docs, PDF, TIF, etc), I can successfully retrieve these files from the database using the following method:
private void GetFilesFromDatabase() {
try
{
const string connStr = #"Data Source=localhost\SQLInstance;Initial Catalog=MyData;Integrated Security=True;";
//Initialize SQL Server connection.
SqlConnection CN = new SqlConnection(connStr);
//Initialize SQL adapter.
SqlDataAdapter ADAP = new SqlDataAdapter("Select ole_id, ole_object From OLE Where ole_id = 21601", CN);
//Initialize Dataset.
DataSet DS = new DataSet();
//Fill dataset with FilesStore table.
ADAP.Fill(DS, "FilesStore");
//Get File data from dataset row.
byte[] FileData = (byte[])DS.Tables["FilesStore"].Rows[0]["ole_object"];
string FileName = #"C:\Temp\Text.doc";
//Write file data to selected file.
using (FileStream fs = new FileStream(FileName, FileMode.Create))
{
fs.Write(FileData, 0, FileData.Length);
fs.Close();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
This file I am retrieving is a Word Doc file according to other information contained in that particular row. When I attempt to open the file after retrieving it to disk the data all appears to be gibberish and is not able to be read. Now I believe that these files were compressed prior to be saved to the database but I don't know how to de-compress them so that they can be viewed, any thoughts on how I may accomplish this? My ultimate goal is to move these images into another database.

Your code to save files look OK. Assuming your original data was .DOC file and you got bad file after saving you pretty much out of luck. You may want to look at the content of the file in binary editor (i.e. Visual Studio's one) to confirm that file is not something obviously different (text/image....).
You need to ask around how files where stored in the database. There is no way this can be answered remotely as it could be compressed, encrypted, split into chunks or even simply corrupted.

Related

Deserialize SQL Server image field back in Excel format

I have a SQL Server table that contains serialized Excel files, with 3 fields:
IdDocument -> int (PK)
DataFile -> image
FileName -> nvarchar
where DataFile contains the Excel file serialized, and FileName the name of the file (with path).
Something like this:
0xD0CF11E0A1B11AE100.....
U:\SAP_R3V4_Validation_Documents\March2012.xls
Now I need to get these files back in Excel format.
How can I accomplish this?
Using C# console application or SQL Server features could be fine.
Thank you in advance.
Luis
Excel files are binary. The xls format is obsolete, replaced since 2007 (15 years ago) by xlsx, a ZIP package containing XML files. What the question shows is how binary data looks in SSMS, not some kind of serialized format.
BTW the image is deprecated, replaced by varbinary(max) in 2005 or 2008 (can't remember).
In any case, reading binary data is the same as reading any other data. A DbDataReader is used to retrieve the query results and strongly typed methods are used to read specific fields per row. In this particular case GetStream() can be used to retrieve the data as a Stream that can be saved to disk:
using var con=new SqlConnection(connectionString)
{
using (var cmd=new SqlCommand(sql,con))
{
using (var reader=cmd.ExecuteReader())
{
while(reader.Read())
{
var path=reader.GetString(2);
var finalPath=Path.Combine(root,Path.GetFileName(path))
using(var stream=reader.GetStream(1))
{
using(var fileStream=File.Create(finalPath))
{
stream.CopyTo(fileStream);
}
}
}
}
}
}
The only thing that's different is the code that reads the field as a stream and saves it to disk
using(var stream=reader.GetStream(1))
{
using(var fileStream=File.Create(finalPath))
{
stream.CopyTo(fileStream);
}
}
The using clauses are used to ensure the data and file streams are closed even in case of error. The path itself is constructed by combining a root folder with the stored filename, not the full path

Open Word file stored in SQL Server

We successfully add word documents in our SQL Server (varbinary column) using some web forms, then, we want some of our staff to be able to download them.
We have some code to display it, but sometimes it does display (in my local environment), sometimes it does not, but then, when it goes live to Production. So, we just want to download it, it doesn't matter if it opens or if it does not (in case you don't have Word installed), we just want to have it downloaded, something like the "Save as..." function. Because in my local environment it works well, but when it goes live to a IIS server, we are not able to retrieve the file (I am guessing, it is because it opens WORD automatically).
Here is the code to retrieve it.
public string showDoc(int id, int numRef)
{
string fileName = Path.GetTempFileName() + ".docx";
Db.Open();
string cuerito = "select doc from tbl_references where [userId]=#id and [refNum]=#numRef";
SqlCommand command = new SqlCommand(cuerito, base.Db);
command.Parameters.AddWithValue("#id", id);
command.Parameters.AddWithValue("#numRef", numRef);
using (SqlDataReader dr = command.ExecuteReader())
{
while (dr.Read())
{
int size = 1024 * 1024;
byte[] buffer = new byte[size];
int readBytes = 0;
int index = 0;
using (FileStream fs = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None))
{
while ((readBytes = (int)dr.GetBytes(0, index, buffer, 0, size)) > 0)
{
fs.Write(buffer, 0, readBytes);
index += readBytes;
}
}
}
}
Db.Close();
return fileName;
}
Is there a way in C# just to do this? Not display but only download it from SQL Server?
EB.
All the code above does is read some data from a binary field and write it to a stream, which gets written to the disk on the server. There's no need to save the file to disk before you offer it for download, you can simply stream the data directly to the client - there are tons of examples and previous questions containing working examples of this process if you google it. They will work with any file, none of this is specific to Word files. And none of it relates to interop in any way.
BTW whether the file downloads directly to the user's disk or is opened up (saved in a temp folder on the user's machine) is largely down to the config of the user's machine, which browser they use, whether the Word plugin is installed in that browser, their general download settings. You can set HTTP headers (again google it) which hint to the browser to just save the file instead of trying to open it, but ultimately it's in the control of the browser, not the server.
Here's one reasonably simple example of sending binary data from a database table as a file download: https://ygtechme.wordpress.com/2012/08/27/downloading-file-from-database-using-c-asp-net/. There are dozens more similar ones with slight variations on the theme available online. But this is the general idea.
The code you posted already does what you ask for.

How to save a binary file accessed from a database in C#?

I have accessed a database which stores employee photos through a c# query. My question is: how can I save the photos to a regular file on my hard drive through a c# program? To create the file, I understand I will be using FileMode.Create and perhaps the SaveFileDialog class?
This is how I have read in the file:
using (SqlConnection connection = new SqlConnection(connectionString))
{
SqlCommand command = new SqlCommand(queryString, connection);
connection.Open();
SqlDataReader reader = command.ExecuteReader();
try
{
while (reader.Read())
{
Console.WriteLine(String.Format("{0}, {1}, {2}, {3}", reader["emp_id"], reader["first_name"], reader["last_name"], reader["photo"]));
FileStream fs = new FileStream(SaveFileDialog.FileName, FileMode.Open); //something of this nature?
}
}
finally
{
reader.Close();
}
}
I have extracted necessary information from this SO question, but it doesn't really help me on saving the file. So, I am asking for some assistance on how to go about saving a binary file, which is a picture, that I want to save on my computer.
File.WriteAllBytes will write bytes to a file of a given name.
In full, something like
File.WriteAllBytes(fileName, (byte[])reader["photo"]);
You can use a save file dialog to save the files, yes. But that's really more a question of your UX design (and application design). In general, loops and dialogs don't play very well - if you make me select 10 different file names to save photos with names you could choose yourself, I'm going to be angry at you :P

Reading Excel files with OleDb or ExcelDataReader return special characters encoded wronlgy

I need to read an EXCEL binary file (xls) in C#.
Basically its working, but i have problems with wrongly encoded characters (german umlauts for example).
Is there some way to specify an encoding? Does Excel files have something like an encoding at all?
The string in the Excel File is
Lydia Hömmerl
When reading with Jet or EDR i get:
Lydia HŠmmerl
I have tried OleDb and the Excel Data Reader project.
Here is the code i use to open and read the file:
var connectionString =
string.Format("Provider=Microsoft.Jet.OLEDB.4.0; data source={0};
Extended Properties=\"Excel 8.0;HDR=no\";", filePath);
var adapter = new OleDbDataAdapter(
"SELECT * FROM [Webshop orders$]", connectionString);
var ds = new DataSet();
adapter.Fill(ds, "Orders");
var data = ds.Tables["Orders"].AsEnumerable();
foreach (var row in data)
{
var str = Convert.ToString(row[0]);
Unicode with C#
There are still many people who don't understand the difference between binary and text, or know what a character encoding is, etc. It is for these people that this page has been written. It mentions a few advanced topics, but only to make the reader aware of their existence, rather than to give much guidance on the topic.

To store and search word documents using C#.NET,ASP.NET

i want to store a word documents (.doc) in the database and i need to provide search over a collection of Word documents and highlight the words too.
I m using VS2005 --> ASP.NET, C#.NET, SQL Server.
you can store it in DB as a BLOB (Binary Large OBject).
Something similar would work
string filePath = "";
string connectionString = "";
FileStream stream =
new FileStream(filePath, FileMode.Open, FileAccess.Read);
BinaryReader reader = new BinaryReader(stream);
byte[] file = reader.ReadBytes((int)stream.Length);
reader.Close();
stream.Close();
SqlCommand command;
SqlConnection connection = new SqlConnection(connectionString);
command =
new SqlCommand("INSERT INTO FileTable (File) Values(#File)", connection);
command.Parameters.Add("#File", SqlDbType.Binary, file.Length).Value = file;
connection.Open();
command.ExecuteNonQuery();
have a look at this post for bit more
details :
How to store word documents in Database using C#
You can store the documents as BLOBs as described above. You then need some way of indexing the contents so you can search.
You could be crude and extract the contents of the Word document as text, store this along with the document and then query this new column using the keywords.
This is not going to be particuarly quick or efficent though. It looks as though Full-Text Indexing may do the trick: http://www.codeproject.com/KB/architecture/sqlfulltextindexing.aspx
Apparently Office documents can be indexed.
When a keyword is entered you can then query the full-text index, find matching documents and then open the documents and highlight the words using either the Office Primary Interop assesmbiles or VSTO.
Is your site public? A good unconventional solution is to use Google. Type into google:
site:www.yoursite.com filetype:doc searchTerm
Here is an example. Notice the View HTML link hightlights the text.
WhiteHouse.gov OMB Search
If you want to get fancy, you could use the WebRequest object to make the request to Google on the server, and then parse out the response to just display the ViewHtml links on your page.

Categories

Resources