Loading binary file from db and process it as openxml - c#

I have such method to load document file from db that is stored as binary and then replace customxml parts with parameters.
Somehow when i convert byte into MemoryStream then process it doesn't work, my custom xml parts are not replaced. But if i use FileStream and read same file from disk then it replaced perfectly!
What is wrong with MemoryStream? i can't also cast MemoryStream to FileStream or create instrance of Stream or etc..
Any suggestion?
private static Stream LoadContent(byte[] content, XmlDocument parameters)
{
//FileStream works perfectly
//Stream fileStream = new FileStream(#"C:\temp\test.docx", FileMode.Open);
Stream documentStream = new MemoryStream();
documentStream.Write(content, 0, content.Length);
//Processes word file, replace custom xml parts with parameters
using (WordprocessingDocument document = WordprocessingDocument.Open(documentStream, true))
{
MainDocumentPart mainPart = document.MainDocumentPart;
Stream partStream = mainPart.CustomXmlParts.First().GetStream();
using (XmlWriter xmlWriter = XmlWriter.Create(partStream, new XmlWriterSettings { CloseOutput = false }))
{
parameters.WriteTo(xmlWriter);
xmlWriter.Flush();
}
mainPart.Document.Save();
}
return documentStream;
}

You might want to try to set the 'Position' propery of the memorystream to 0 after writing data to it and before reading it again.
Alernatively you can also pass the byte array to the constructor of the memorystream instead of calling writer.
edit
I see according to MSDN that the 'Document.Save' method will flush the stream to allow propper saving. ( http://msdn.microsoft.com/en-us/library/cc840441.aspx ).
However MemoryStream wont do anything on flush ( http://msdn.microsoft.com/en-us/library/system.io.memorystream.flush.aspx ).
You could try to create a new MemoryStream and then pass that as a parameter to the 'Document.Save' method.

Related

Why my PDF is not readable after edited by iText?

My PDF is not readable after tried to edit the text.
How to make it works ?
my error message :
Adobe Reader could not open '495049.pdf' because it is either not a supported file type or because the file has been damaged (for example, it was sent as email attachment and wasn't correctly decoded)
Basically the objective is to edit PDF doc and replace particular text.
Input already in binary stream (byte[ ])
I worked on C# environment & iText for the PDF editing lib.
Here's my piece of code :
using (PdfReader reader = new PdfReader(doc.FileStream))
{
PdfDictionary dict = reader.GetPageN(1);
PdfObject pdfObject = dict.GetDirectObject(PdfName.CONTENTS);
if (pdfObject.IsStream())
{
PRStream stream = (PRStream)pdfObject;
byte[] data = PdfReader.GetStreamBytes(stream);
stream.SetData(System.Text.Encoding.ASCII.GetBytes(System.Text.Encoding.ASCII.GetString(data).Replace("[ReplacmentText]", "Hello World")));
}
using (MemoryStream ms = new MemoryStream())
{
var ignored = new PdfStamper(reader, ms);
reader.Close();
return ms.ToArray();
}
}
Your main mistake is that you retrieve the contents of the memory stream before closing the stamper; actually you don't close it at all!
Only when closing the stamper, the final part of the PDF is written. Thus:
using (MemoryStream ms = new MemoryStream())
{
var ignored = new PdfStamper(reader, ms);
ignored.Close();
reader.Close();
return ms.ToArray();
}
Your other problem (probably not relevant for your current test documents but in general):
stream.SetData(System.Text.Encoding.ASCII.GetBytes(System.Text.Encoding.ASCII.GetString(data).Replace("[ReplacmentText]", "Hello World")));
This assumes very much, especially that the stream content only contains ASCII bytes, that the place holder "[ReplacementText]" (I assume this is the correct spelling) occurs in one piece and in the immediate content streams, that the font used to draw the place holder and its replacement uses an ASCII'ish encoding, and that this font has glyphs for all characters in "Hello World". Neither of these assumptions are automatically true.

Is it possible to write a packaging.package to a stream without having to save it to a file first?

I have a System.IO.Packaging.Package in memory (it is a WordprocessingDocument) and want to stream it down to browser to save it. The word document has been modified by the MVC-based application and the resulting file has been modified for the current request.
I understand the package represents a 'zip' file containing a number of parts. These parts include headers, footers and main body document. I've modified each individually and now want to stream the package back to the user.
I can get the individual part streams... package.GetPart(new Uri("/word/document.xml", UriKind.Relative)).GetStream()
However I'm missing how to get an output stream on the entire document (package)- without writing to the file system.
Thanks in advance
No- what I think I need is something like this... I've already read in the template document and made modifications in memory. Now I want to stream a modified document (leaving the template un-touched) back to the user.
MemoryStream stream = new MemoryStream();
WordprocessingDocument docOut =
WordprocessingDocument.Create( stream, WordprocessingDocumentType.Document);
foreach (var part in package.GetParts())
{
using (StreamReader streamReader = new StreamReader(part.GetStream()))
{
PackagePart newPart = docOut.Package.CreatePart(
part.Uri, part.ContentType );
using (StreamWriter streamWriter = new StreamWriter(newPart.GetStream(FileMode.Create)))
{
streamWriter.Write(streamReader.ReadToEnd());
}
}
}
Unfortunately- this produces a 'corrupt' word document...
OpenXmlPackage.Close Method saves all changes in all parts to the underlying store. If you opened the package from a stream, just use that stream:
public Stream packageStream() {
var ms = new MemoryStream();
var wrdPk = WordprocessingDocument.Create(ms, WordprocessingDocumentType.Document);
// Build the package ...
var docPart = wrdPk.AddMainDocumentPart();
docPart.Document = new Document(
new Body(new Paragraph(new Run(new Text("Hello world.")))));
// Flush all changes
wrdPk.Close();
return ms;
}

Cannot access a closed Stream while creating a downloadable text file in ASP MVC 3

Im trying to prompt a downloadable text file (.txt), but I get this error:
Cannot access a closed Stream.
I have looked at simular questions in here:
Cannot Access Closed Stream
But it was not very useful.
Here is my code:
private FileStreamResult Export()
{
string name = "filename.txt";
MemoryStream stream = new MemoryStream();
using (StreamWriter writer = new StreamWriter(stream))
{
StringBuilder sb = new StringBuilder();
sb.Append("A text...");
writer.WriteLine(sb.ToString());
}
return File(stream, "text/plain", name);
}
UPDATE (working copy):
This gives me an blank text file.
private FileResult Export()
{
string name = "filename.txt";
MemoryStream stream = new MemoryStream();
StreamWriter writer = new StreamWriter(stream);
StringBuilder sb = new StringBuilder();
sb.Append("A text...");
writer.WriteLine(sb.ToString());
writer.Flush();
stream.Seek(0, SeekOrigin.Begin);
return File(stream, "text/plain", name);
}
That is correct, when you wrap a stream in another stream, calling .Close() or .Dispose() on any of them will dispose the whole stream. In this case, wrapping the MemoryStream in a StreamWriter means that when the using statement completes the StreamWriter and MemoryStream are both disposed.
My guess is since you are returning a FileStreamResult the encapsulating File will close the stream for you after the stream is no longer used. In this case, you do not want to use the using statement and will want to leave the stream open when returning it.
UPDATE
Since a stream is forward access you'll need to see the stream back to the beginning to allow the data to be read back out.
stream.Seek(0, SeekOrigin.Begin);
Just remove that using statement - you are passing disposed object reference to File method and you that's the reason why you get exception. From MSDN,
The StreamWriter object calls Dispose on the provided Stream object
when StreamWriter.Dispose is called.
I believe File will dispose stream by itself after usage (not verified by looking at source code).
UPDATE:
writer.Flush(); before return statement should help you
You have to set the position of the memorystream to 0 before using it in your FileStreamResult, otherwise it will be read from current position (IE the end of the stream).
stream.Position = 0;
return File(stream, "text/plain", name);
Just had the same thing.
I know this thread is ancient, just hoping to aid others having the same issue.
Replace the FileStreamResult type on your action with FileResult.

unable to save dynamically created MemoryStream with rebex sftp

I'm using StreamWriter to generate a dynamic file and holding it in a MemoryStream. Everything appears to be alright until I go to save the file using rebex sftp.
The example they give on their site works fine:
// upload a text using a MemoryStream
string message = "Hello from Rebex FTP for .NET!";
byte[] data = System.Text.Encoding.Default.GetBytes(message);
System.IO.MemoryStream ms = new System.IO.MemoryStream(data);
client.PutFile(ms, "message.txt");
However the code below does not:
using (var stream = new MemoryStream())
{
using (var writer = new StreamWriter(stream))
{
writer.AutoFlush = true;
writer.Write("test");
}
client.PutFile(stream, "test.txt");
}
The file "test.txt" is saved, however it is empty. Do I need to do more than just enable AutoFlush for this to work?
After writing to the MemoryStream, the stream is positioned at the end. The PutFile method reads from the current position to the end. That's exactly 0 bytes.
You need to position the stream at the beginning before passing it to PutFile:
...
}
stream.Seek(0, SeekOrigin.Begin);
client.PutFile(stream, "test.txt");
You may also need to prevent the StreamWriter from disposing the MemoryStream:
var writer = new StreamWriter(stream);
writer.Write("test");
writer.Flush();
stream.Seek(0, SeekOrigin.Begin);
client.PutFile(stream, "test.txt");

iTextSharp + FileStream = Corrupt PDF file

I am trying to create a pdf file with iTextSharp. My attempt writes the content of the pdf to a MemoryStream so I can write the result both into file and a database BLOB. The file gets created, has a size of about 21kB and it looks like a pdf when opend with Notepad++. But my PDF viewer says it's currupted.
Here is a little code snippet (only tries to write to a file, not to a database):
Document myDocument = new Document();
MemoryStream myMemoryStream = new MemoryStream();
PdfWriter myPDFWriter = PdfWriter.GetInstance(myDocument, myMemoryStream);
myDocument.Open();
// Content of the pdf gets inserted here
using (FileStream fs = File.Create("D:\\...\\aTestFile.pdf"))
{
myMemoryStream.WriteTo(fs);
}
myMemoryStream.Close();
Where is the mistake I make?
Thank you,
Norbert
I think your problem was that you weren't properly adding content to your PDF. This is done through the Document.Add() method and you finish up by calling Document.Close().
When you call Document.Close() however, your MemoryStream also closes so you won't be able to write it to your FileStream as you have. You can get around this by storing the content of your MemoryStream to a byte array.
The following code snippet works for me:
using (MemoryStream myMemoryStream = new MemoryStream()) {
Document myDocument = new Document();
PdfWriter myPDFWriter = PdfWriter.GetInstance(myDocument, myMemoryStream);
myDocument.Open();
// Add to content to your PDF here...
myDocument.Add(new Paragraph("I hope this works for you."));
// We're done adding stuff to our PDF.
myDocument.Close();
byte[] content = myMemoryStream.ToArray();
// Write out PDF from memory stream.
using (FileStream fs = File.Create("aTestFile.pdf")) {
fs.Write(content, 0, (int)content.Length);
}
}
I had similar issue. My file gets downloaded but the file size will be 13Bytes. I resolved the issue when I used binary writer to write my file
byte[] bytes = new byte[0];
//pass in your API response into the bytes initialized
using (StreamWriter streamWriter = new StreamWriter(FilePath, true))
{
BinaryWriter binaryWriter = new BinaryWriter(streamWriter.BaseStream);
binaryWriter.Write(bytes);
}
Just some thoughts - what happens if you replace the memory stream with a file stream? Does this give you the result you need? This will at least tell you where the problem could be.
If this does work, how do the files differ (in size and binary representation)?
Just a guess, but have you tried seeking to the beginning of the memory stream before writing?
myMemoryStream.Seek(0, SeekOrigin.Begin);
Try double checking your code that manipulates the PDF with iText. Make sure you're calling the appropriate EndText method of any PdfContentByte objects, and make sure you call myDocument.Close() before writing the file to disk. Those are things I've had problems with in the past when generating PDFs with iTextSharp.
documentobject.Close();
using (FileStream fs = System.IO.File.Create(path)){
Memorystreamobject.WriteTo(fs);
}

Categories