I am trying to store an uploaded file (via ajax file upload) into a LONGBLOB column of a MySQL database. Reason for a LONGBLOB, the user is allowed to upload a file up until 10MB in file size.
The first issue is that I couldn't upload just the file byte[] into the column, as it complained about an "incorrect string value".
So, I decided to do a Convert.ToBase64String of the file byte[] and store that. No problem (I hope).
My main problem is that I want to retrieve that stored blob and write it to an Outputstream in order to view the file in the browser. The file is however corrupt.
The difference that I do pick up is that the byte[] length of the original file is significantly less than the byte[] of the blob (after I retrieve and convert it back to a byte[]).
So, code wise, here is what I have attempted for the saving of the uploaded file:
byte[] fileData = null;
//file is the uploaded file
file.InputStream.Position = 0;
using (var reader = new BinaryReader(file.InputStream))
{
fileData = reader.ReadBytes(file.ContentLength);
}
var encryptedFileStream = Convert.ToBase64String(fileData);
//Storing encryptedFileStream to LONGBLOB type
Below is what I have attempted for the reading of the blob into a OutputStream:
var decryptedFileStream = Convert.FromBase64String(Convert.ToBase64String(file.FileStream)); //file.FileStream is a byte[] datatype.
WebClient client = new WebClient();
var response = ((Handler)ExecutionContext).Response;
response.Clear();
response.ContentType = file.FileExtension;
response.AppendHeader("content-disposition", (inline ? "inline" : "attachment") + "; filename=" + file.FileName);
response.AppendHeader("content-length", decryptedFileStream.Length.ToString());
response.OutputStream.Write(decryptedFileStream, 0, decryptedFileStream.Length);
I am able to upload the document but when I'm viewing/downloading it, there seems to be an error. It says it ran into a problem opening this PDF.
Ran into a problem
I have the following code
using (var stream = new System.IO.MemoryStream())
{
byte[] myByte = System.Text.ASCIIEncoding.Default.GetBytes(documentBody);
foreach (byte element in myByte)
{
stream.WriteByte(element);
}
stream.Seek(0, SeekOrigin.Begin);
var newFile = new FileCreationInformation { Url = fileName, ContentStream = stream, Overwrite = true };
file = list.RootFolder.Files.Add(newFile);
file.CheckOut();
file.CheckIn(string.Empty, CheckinType.MajorCheckIn);
context.Load(file);
context.ExecuteQuery();
}
The documentBody is the field documentbody from Annotation (note). Is there something wrong with the stream?
The documentBody is Base64 encoded in CRM, so you many need to decode it first before saving into SharePoint.
Try this to get the document data.
byte[] data = Convert.FromBase64String(e.Attributes["documentbody"].ToString());
hiiii,
i want to read mp3 file by using binary reader, my code is :
using (BinaryReader br = new BinaryReader(File.Open("Songs/testbinary.mp3", FileMode.Open)))
{
int length = (int)br.BaseStream.Length;
byte[] bytes = br.ReadBytes(length);
txtBinary.Text = bytes.ToString();
}
.......
when i execute this code it shows and exception:
The process cannot access the file 'URL\testbinary.mp3' because it is being used by another process.
where "URL" is my actual file location.
You open the same file twice (without any sharing option). To read the content of a file as bytes you can use File.ReadAllBytes
byte[] bytes = File.ReadAllBytes("Songs/testbinary.mp3");
BTW: Don't forget txtBinary.Text = bytes.ToString(); doesn't give you what you think. You will have to use BitConverter.ToString or Convert.ToBase64String
I have created code to upload an image into SQL Server.
Here is the code to convert the image into bytes:
//Use FileInfo object to get file size.
FileInfo fInfo = new FileInfo(p);
//Open FileStream to read file
FileStream fStream = new FileStream(p, FileMode.Open, FileAccess.Read);
byte[] numBytes = new byte[fStream.Length];
fStream.Read(numBytes, 0, Convert.ToInt32(fStream.Length));
//Use BinaryReader to read file stream into byte array.
//BinaryReader br = new BinaryReader(fStream);
//When you use BinaryReader, you need to supply number of bytes to read from file.
//In this case we want to read entire file. So supplying total number of bytes.
// data = br.ReadBytes((int)numBytes);
return numBytes;
And here is the code to add the bytes to a SqlCommand parameter as values:
objCmd.Parameters.Add("#bill_Image", SqlDbType.Binary).Value = imageData;
objCmd.ExecuteNonQuery();
But I am getting error
String or binary data would be truncated. The statement has been terminated
How can I overcome this problem?
Error is clearly indicating that you're trying to save more bytes than allowed by the field definition.
Not sure what sql type you're using for bill_Image but an appropiated field definition to store an image would be varbinary(MAX).
Check definition of the bill_Image column in your database.
it should be something like
bill_Image varbinary(X)
Just increase X or put there MAX instead of a number (if you have more than 8 000 bytes image)
Info about binary/varbinary type here
I have a stream of bytes which actually (if put right) will form a valid Word file, I need to convert this stream into a Word file without writing it to disk, I take the original stream from SQL Server database table:
ID Name FileData
----------------------------------------
1 Word1 292jf2jf2ofm29fj29fj29fj29f2jf29efj29fj2f9 (actual file data)
the FileData field carries the data.
Microsoft.Office.Interop.Word.Application word = new Microsoft.Office.Interop.Word.Application();
Microsoft.Office.Interop.Word.Document doc = new Microsoft.Office.Interop.Word.Document();
doc = word.Documents.Open(#"C:\SampleText.doc");
doc.Activate();
The above code opens and fill a Word file from File System, I don't want that, I want to define a new Microsoft.Office.Interop.Word.Document, but I want to fill its content manually from byte stream.
After getting the in-memory Word document, I want to do some parsing of keywords.
Any ideas?
Create an in memmory file system, there are drivers for that.
Give word a path to an ftp server path (or something else) which you then use to push the data.
One important thing to note: storing files in a database is generally not good design.
You could look at how Sharepoint solves this. They have created a web interface for documents stored in their database.
Its not that hard to create or embed a webserver in your application that can serve pages to Word. You don't even have to use the standard ports.
There probably isn't any straight-forward way of doing this. I found a couple of solutions searching for it:
Use the OpenOffice SDK to manipulate the document instead of Word
Interop
Write the data to the clipboard, and then from the Clipboard to Word
I don't know if this does it for you, but apparently the API doesn't provide what you're after (unfortunately).
There are really only 2 ways to open a Word document programmatically - as a physical file or as a stream. There's a "package", but that's not really applicable.
The stream method is covered here: https://learn.microsoft.com/en-us/office/open-xml/how-to-open-a-word-processing-document-from-a-stream
But even it relies on there being a physical file in order to form the stream:
string strDoc = #"C:\Users\Public\Public Documents\Word13.docx";
Stream stream = File.Open(strDoc, FileMode.Open);
The best solution I can offer would be to write the file out to a temp location where the service account for the application has permission to write:
string newDocument = #"C:\temp\test.docx";
WriteFile(byteArray, newDocument);
If it didn't have permissions on the "temp" folder in my example, you would simply just add the service account of your application (application pool, if it's a website) to have Full Control of the folder.
You'd use this WriteFile() function:
/// <summary>
/// Write a byte[] to a new file at the location where you choose
/// </summary>
/// <param name="byteArray">byte[] that consists of file data</param>
/// <param name="newDocument">Path to where the new document will be written</param>
public static void WriteFile(byte[] byteArray, string newDocument)
{
using (MemoryStream stream = new MemoryStream())
{
stream.Write(byteArray, 0, (int)byteArray.Length);
// Save the file with the new name
File.WriteAllBytes(newDocument, stream.ToArray());
}
}
From there, you can open it with OpenXML and edit the file. There's no way to open a Word document in byte[] form directly into an instance of Word - Interop, OpenXML, or otherwise - because you need a documentPath, or the stream method mentioned earlier that relies on there being a physical file. You can edit the bytes you would get by reading the bytes into a string, and XML afterwards, or just edit the string, directly:
string docText = null;
byte[] byteArray = null;
using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(documentPath, true))
{
using (StreamReader sr = new StreamReader(wordDoc.MainDocumentPart.GetStream()))
{
docText = sr.ReadToEnd(); // <-- converts byte[] stream to string
}
// Play with the XML
XmlDocument xml = new XmlDocument();
xml.LoadXml(docText); // the string contains the XML of the Word document
XmlNodeList nodes = xml.GetElementsByTagName("w:body");
XmlNode chiefBodyNode = nodes[0];
// add paragraphs with AppendChild...
// remove a node by getting a ChildNode and removing it, like this...
XmlNode firstParagraph = chiefBodyNode.ChildNodes[2];
chiefBodyNode.RemoveChild(firstParagraph);
// Or play with the string form
docText = docText.Replace("John","Joe");
// If you manipulated the XML, write it back to the string
//docText = xml.OuterXml; // comment out the line above if XML edits are all you want to do, and uncomment out this line
// Save the file - yes, back to the file system - required
using (StreamWriter sw = new StreamWriter(wordDoc.MainDocumentPart.GetStream(FileMode.Create)))
{
sw.Write(docText);
}
}
// Read it back in as bytes
byteArray = File.ReadAllBytes(documentPath); // new bytes, ready for DB saving
Reference:
https://learn.microsoft.com/en-us/office/open-xml/how-to-search-and-replace-text-in-a-document-part
I know it's not ideal, but I have searched and not found a way to edit the byte[] directly without a conversion that involves writing out the file, opening it in Word for the edits, then essentially re-uploading it to recover the new bytes. Doing byte[] byteArray = Encoding.UTF8.GetBytes(docText); prior to re-reading the file will corrupt them, as would any other Encoding I tried (UTF7,Default,Unicode, ASCII), as I found when I tried to write them back out using my WriteFile() function, above, in that last line. When not encoded and simply collected using File.ReadAllBytes(), and then writing the bytes back out using WriteFile(), it worked fine.
Update:
It might be possible to manipulate the bytes like this:
//byte[] byteArray = File.ReadAllBytes("Test.docx"); // you might be able to assign your bytes here, instead of from a file?
byte[] byteArray = GetByteArrayFromDatabase(fileId); // function you have for getting the document from the database
using (MemoryStream mem = new MemoryStream())
{
mem.Write(byteArray, 0, (int)byteArray.Length);
using (WordprocessingDocument wordDoc =
WordprocessingDocument.Open(mem, true))
{
// do your updates -- see string or XML edits, above
// Once done, you may need to save the changes....
//wordDoc.MainDocumentPart.Document.Save();
}
// But you will still need to save it to the file system here....
// You would update "documentPath" to a new name first...
string documentPath = #"C:\temp\newDoc.docx";
using (FileStream fileStream = new FileStream(documentPath,
System.IO.FileMode.CreateNew))
{
mem.WriteTo(fileStream);
}
}
// And then read the bytes back in, to save it to the database
byteArray = File.ReadAllBytes(documentPath); // new bytes, ready for DB saving
Reference:
https://learn.microsoft.com/en-us/previous-versions/office/office-12//ee945362(v=office.12)
But note that even this method will require saving the document, then reading it back in, in order to save it to bytes for the database. It will also fail if the document is in .doc format instead of .docx on that line where the document is being opened.
Instead of that last section for saving the file to the file system, you could just take the memory stream and save that back into bytes once you are outside of the WordprocessingDocument.Open() block, but still inside the using (MemoryStream mem = new MemoryStream() { ... } statement:
// Convert
byteArray = mem.ToArray();
This will have your Word document byte[].