Reading a docx (binary) from a SQL Server database and convert it into letter (docx) - sql-server

OK I managed to upload the word DOCX into my SQL Server database into a varbinary (Max) column.
I can retrieve the DOCX from the database and covert it from varbinary back into an array and offer it as a download with:
Byte[] bytes = (Byte[])dt.Rows[0]["TD_DocFile"];
Response.Buffer = true;
Response.Charset = "";
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.ContentType = dt.Rows[0]["TD_DocContentType"].ToString();
Response.AddHeader("content-disposition", "attachment;filename="
+ dt.Rows[0]["TD_DocTitle"].ToString());
Response.BinaryWrite(bytes);
Response.Flush();
Response.End();
Instead of downloading the document I would prefer to use it in variable so I exchange placeholders in it.
I tried to find a way to convert it to a string or so I can use it for docx eg.
DocX letter = this.document();
Best option I saw so far was the filestream version
public static MemoryStream databaseFileRead(string varID) {
MemoryStream memoryStream = new MemoryStream();
using (var varConnection = Locale.sqlConnectOneTime(Locale.sqlDataConnectionDetails))
using (var sqlQuery = new SqlCommand(#"SELECT [RaportPlik] FROM [dbo].[Raporty] WHERE [RaportID] = #varID", varConnection)) {
sqlQuery.Parameters.AddWithValue("#varID", varID);
using (var sqlQueryResult = sqlQuery.ExecuteReader())
if (sqlQueryResult != null) {
sqlQueryResult.Read();
var blob = new Byte[(sqlQueryResult.GetBytes(0, 0, null, 0, int.MaxValue))];
sqlQueryResult.GetBytes(0, 0, blob, 0, blob.Length);
//using (var fs = new MemoryStream(memoryStream, FileMode.Create, FileAccess.Write)) {
memoryStream.Write(blob, 0, blob.Length);
//}
}
}
return memoryStream;
}
But I couldn't convert the binary array bytes nor the memory stream into a variable docx would understand. Maybe I just looked for the wrong conversation. Can someone give me a hint please?
The field is called TD_DocContentType from the database. I can accept that I am weak on the conversion in this instance. I can't see what I am doing wrong. Need a new idea please.
Kind Regards,
Rene

I found the solution for my problem. Took a while and lot of more research to do. I tried to tackle the problem from the wrong angle.
This solution reads the binary field from the database and writes it as a file to an internal web folder called doctemp.
private void download(DataTable dt)
{
var physicalPath = Server.MapPath("~\\doctemp\\{0}");
string outputFileName = string.Format(physicalPath, dt.Rows[0]["TD_DocTitle"]);
filename = outputFileName;
Byte[] bytes = (Byte[])dt.Rows[0]["TD_DocFile"];
File.WriteAllBytes(outputFileName, bytes);
}

Related

SSIS OLE DB Destination not inserting accented characters

I have the following table :
CREATE TABLE DI_Simulation
(
[city] nvarchar(255),
[profession] nvarchar(255)
);
I load the data from an URL with a Script task where I created a class Simulation and added two string attributes. I then deserialize the downloaded JSON data and create output rows.
I specify that the output columns city and profession are of type DT_WSTR but the following characters [é,à,è,...] are always replaced...
I tried different collations on both columns but no changes were seen. I also tried forcing UTF8 conversion on the Script Task but that also didn't work.
Any suggestions ?
EDIT: I should also mention that I have other tables where the insertion is made correctly, but this one especially has this issue, which I'm thinking the Script Task has something to do with it.
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Ssl3;
// Convert json string to .net object using the old school JavaScriptSerializer class
string Uri = "https://....";
JavaScriptSerializer serialize = new JavaScriptSerializer
{
MaxJsonLength = Int32.MaxValue,
};
var simulation = serialize.Deserialize<Simulation[]>(DownloadJson(Uri));
EDIT 2:
WebClient client = new WebClient();
Stream stream = client.OpenRead(Url);
StreamReader streamreader = new StreamReader(stream, System.Text.Encoding.GetEncoding(1252));
var ags = streamreader.ReadToEnd();
/*System.IO.File.WriteAllText(#"C:\Users\hhamdani\Desktop\Data Integration Objetcs\simulation_data.json",
ags,
System.Text.Encoding.GetEncoding(1252));*/
var simulation = serialize.Deserialize<Simulation[]>(ags);
Instead of downloading with DownloadJson, I used streamreader to get the Json Data from the URL and forced the Encoding, when I save the data on a txt file it's good, but on the Database it's the same issue.
Works fine from a script source component based on my reproduction
Setup
Table creation
A trivial table with two columns
CREATE TABLE dbo.[SO_71842511] (
[TestCase] int,
[SomeText] nvarchar(50)
)
SCR Do Unicode
Proof that we can inject unicode characters into the data flow task from a script source.
Define the Script Task as a Source. Add 2 columns to the output, one int, one DT_WSTR
using System;
using System.Data;
using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
using Microsoft.SqlServer.Dts.Runtime.Wrapper;
[Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute]
public class ScriptMain : UserComponent
{
public override void CreateNewOutputRows()
{
Output0Buffer.AddRow();
Output0Buffer.SomeText = "e e plain";
Output0Buffer.TestCase = 0;
Output0Buffer.AddRow();
Output0Buffer.SomeText = "é e forward";
Output0Buffer.TestCase = 1;
Output0Buffer.AddRow();
Output0Buffer.SomeText = "à a back";
Output0Buffer.TestCase = 2;
Output0Buffer.AddRow();
Output0Buffer.SomeText = "è e backward";
Output0Buffer.TestCase = 3;
}
}
Results
WebClient client = new WebClient();
Stream stream = client.OpenRead(Url);
StreamReader streamreader = new StreamReader(stream, System.Text.Encoding.UTF8);
var ags = streamreader.ReadToEnd();
This did the job for me.
Thanks #billinkc

Storing upload file as binary data in SQL Server database

I have been struggling with this issue. I'm trying to upload a file to the server and save it as binary data in the database.
I know how to upload a file to the server and it's working fine.
I need to know how to save the file as binary data in the database.
This is what I have accomplished:
In a SQL Server database, I have a table called files with the following columns:
Id, int, identity column
FileName, nvarchar(50)
UploadDate, datetime
FileContent, varbinary(max)
HomeController.cs:
[HttpPost]
public ActionResult Index(HttpPostedFileBase[] files)
{
try
{
foreach (var file in files)
{
// extract only the filename
var fileName = Path.GetFileName(file.FileName);
// extract the file content to byte array
var content = new byte[file.ContentLength];
// reads the content from stream
file.InputStream.Read(content, 0, file.ContentLength);
//get file extesion
var fileExtension = Path.GetExtension(fileName);
//save file name as uniqe
var uniqueFileName = Guid.NewGuid().ToString();
Files fu = new Files
{
FileName = uniqueFileName,
UploadDate = DateTime.Now,
FileContent = content
};
DB.Files.Add(fu);
DB.SaveChanges();
}
}
catch (Exception e) { }
// redirect back to the index action to show the form once again
return RedirectToAction("Index");
}
index.cshtml:
#using (Html.BeginForm("Index", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<input type="file" name="files" multiple/>
<input type="submit" value="OK" />
}
This code inserts a records into the database table, and the record looks like this:
Id FileName UploadDate FileContent
1 716d30a5-8019-4ec9-a5e9-5b3966296bfc 2015-11-27 21:50:27.037 <Binary data>
I don't know why the fileContent column gets filled with the text <Binary data>.
Since file content data type is binary, Sql server manage this as binary data type internally. You can not see the binary directly by looking into Table.
If you want to view Binary data in SSMS, give a try to this
This is a example to retrieve the binday data
// Assumes that connection is a valid SqlConnection object.
SqlCommand command = new SqlCommand(
"SELECT pub_id, logo FROM pub_info", connection);
// Writes the BLOB to a file (*.bmp).
FileStream stream;
// Streams the BLOB to the FileStream object.
BinaryWriter writer;
// Size of the BLOB buffer.
int bufferSize = 100;
// The BLOB byte[] buffer to be filled by GetBytes.
byte[] outByte = new byte[bufferSize];
// The bytes returned from GetBytes.
long retval;
// The starting position in the BLOB output.
long startIndex = 0;
// The publisher id to use in the file name.
string pubID = "";
// Open the connection and read data into the DataReader.
connection.Open();
SqlDataReader reader = command.ExecuteReader(CommandBehavior.SequentialAccess);
while (reader.Read())
{
// Get the publisher id, which must occur before getting the logo.
pubID = reader.GetString(0);
// Create a file to hold the output.
stream = new FileStream(
"logo" + pubID + ".bmp", FileMode.OpenOrCreate, FileAccess.Write);
writer = new BinaryWriter(stream);
// Reset the starting byte for the new BLOB.
startIndex = 0;
// Read bytes into outByte[] and retain the number of bytes returned.
retval = reader.GetBytes(1, startIndex, outByte, 0, bufferSize);
// Continue while there are bytes beyond the size of the buffer.
while (retval == bufferSize)
{
writer.Write(outByte);
writer.Flush();
// Reposition start index to end of last buffer and fill buffer.
startIndex += bufferSize;
retval = reader.GetBytes(1, startIndex, outByte, 0, bufferSize);
}
// Write the remaining buffer.
writer.Write(outByte, 0, (int)retval - 1);
writer.Flush();
// Close the output file.
writer.Close();
stream.Close();
}
// Close the reader and the connection.
reader.Close();
connection.Close();
Source : MSDN

How to deliver bitmap to the server?

Writing my first silverlight application.
I need to deliver some bitmap that the customer will choose ( used OpenFileDialog ) to the server side ( using web service ).
After the customer choosing the bitmap - i cant access the file and break hit to byte array because i dont see the file full path on the OpenFileDialog object properties.
How can i do it ?
( i have method that get Bitmap and return the bitmap as byte array )
I did that before, here is part of it:
OpenFileDialog dialog = new OpenFileDialog();
dialog.Filter = "Images (*.png; *.jpg)| *.png; *.jpg";
dialog.Multiselect = false;
if (dialog.ShowDialog() == true)
{
using (System.IO.Stream stream = dialog.File.OpenRead())
{
BinaryReader binaryReader = new BinaryReader(stream);
// here are the bytes you want, put them somewhere to send them to the server
byte[] imageBytes = binaryReader.ReadBytes((int)stream.Length);
// here is the filename if you need it
string filename = System.IO.Path.GetFileNameWithoutExtension(dialog.File.Name);
stream.Close();
}
}

Storing binary objects in SQL Server with LINQ

I'm trying to do the same thing as in this question, but am having problems.
Can you share with me how you prepared your objects prior to inserting and updating the database?
I have a List<myObject> that I want to store as a VarBinary(max) in SQL Server 2008.
You will need to convert your List<object> to a byte[]. You don't need Linq specifically but I assume you are using Linq To Sql? Before storing your object in the property that should contain the binary you need to convert it to a byte[]. Here is some example code to do what you need (Source Link):
// Convert an object to a byte array
private byte[] ObjectToByteArray(Object obj)
{
if(obj == null)
return null;
BinaryFormatter bf = new BinaryFormatter();
MemoryStream ms = new MemoryStream();
bf.Serialize(ms, obj);
return ms.ToArray();
}
// Convert a byte array to an Object
private Object ByteArrayToObject(byte[] arrBytes)
{
MemoryStream memStream = new MemoryStream();
BinaryFormatter binForm = new BinaryFormatter();
memStream.Write(arrBytes, 0, arrBytes.Length);
memStream.Seek(0, SeekOrigin.Begin);
Object obj = (Object) binForm.Deserialize(memStream);
return obj;
}

convert object(i.e any object like person, employee) to byte[] in silverlight

i have a person object and need to store it as byte[] and again retrieve that byte[] and convert to person object
and BinaryFormatter is not availabe in silverlight
Because the namespaces mentioned by t0mm13b are not part of the Silverlight .NET engine, the correct way to is to use this workaround leveraging the data contract serializer:
http://forums.silverlight.net/forums/t/23161.aspx
From the link:
string SerializeWithDCS(object obj)
{
if (obj == null) throw new ArgumentNullException("obj");
DataContractSerializer dcs = new DataContractSerializer(obj.GetType());
MemoryStream ms = new MemoryStream();
dcs.WriteObject(ms, obj);
return Encoding.UTF8.GetString(ms.GetBuffer(), 0, (int)ms.Position);
}
If you really need binary and want it to be super fast and very small, then you should use protobuf from Google.
http://code.google.com/p/protobuf-net/
Look at these performance numbers. Protobuf is far and away the fastest and smallest.
I've used it for WCF <--> Silverlight with success and would not hesitate to use it again for a new project.
I have used XML Serializer to convert the object to a string and them convert the string to byte[] successfully in Silverlight.
object address = new Address();
System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(Address));
StringBuilder stringBuilder = new StringBuilder();
using (StringWriter writer = new StringWriter(stringBuilder))
{
serializer.Serialize(writer, address);
}
System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
byte[] data = encoding.GetBytes(stringBuilder.ToString());
Look at custom binary serialization and compression here
and here
Use the serialized class to convert the object into a byte via using a MemoryStream
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization;
....
byte[] bPersonInfo = null;
using (MemoryStream mStream = new MemoryStream())
{
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(mStream, personInfo);
bPersonInfo = mStream.ToArray();
}
....
// Do what you have to do with bPersonInfo which is a byte Array...
// To Convert it back
PersonInfo pInfo = null;
using (MemoryStream mStream = new MemoryStream(bPersonInfo)){
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter bf = new BinaryFormatter();
pInfo = (PersonInfo)bf.DeSerialize(mStream);
}
// Now pInfo is a PersonInfo object.
Hope this helps,
Best regards,
Tom.

Resources