C# Spire Document.SaveToStream not working - c#

I have the following code but it is just creating a 0kb empty file.
using (var stream1 = new MemoryStream())
{
MemoryStream txtStream = new MemoryStream();
Document document = new Document();
fileInformation.Stream.CopyTo(stream1);
document.LoadFromStream(stream1, FileFormat.Auto);
document.SaveToStream(txtStream, FileFormat.Txt);
StreamReader reader = new StreamReader(txtStream);
string text = reader.ReadToEnd();
System.IO.File.WriteAllText(fileName + ".txt", text);
}
I know the data is successfully loaded into document because if do document.SaveToTxt("test.txt", Encoding.UTF8);
instead of the SaveToStream line it exports the file properly.
What am I doing wrong?

When copying a stream, you need to take care to reset the position to 0 if copying. As seen in the answer here, you can do something like this to your streams:
stream1.Position = 0;
txtStream.Position = 0;

Related

Converting DotNetZip memory stream to string

I am trying to read a file within a zip to check if that file has a certain string in it. But I can seem to get the "file" (memory stream) into a string in order to search it.
When I use the following code "stringOfStream" is always blank, what am I doing wrong? The reader always has a length and read byte returns different numbers.
using (ZipFile zip = ZipFile.Read(currentFile.FullName))
{
ZipEntry e = zip[this.searchFile.Text];
using (MemoryStream reader = new MemoryStream())
{
e.Extract(reader);
var stringReader = new StreamReader(reader);
var stringOfStream = stringReader.ReadToEnd();
}
}
Thanks
I think when you call Extract the position of the stream goes to the end of the file, so you need to reposition again to get the data.
Can you try this please :
using (ZipFile zip = ZipFile.Read(currentFile.FullName))
{
ZipEntry e = zip[this.searchFile.Text];
using (MemoryStream reader = new MemoryStream())
{
e.Extract(reader);
reader.Position = 0;
var stringReader = new StreamReader(reader);
var stringOfStream = stringReader.ReadToEnd();
}
}
Check if it works or not.

itextsharp PDF concatenation not working

i have a webapi where i have route to concatenate pdfs and return the byte array using memorystream
public HttpResponseMessage ConcatPDFs(string id, ICollection<int> pdfs) {
using (var db = new ApplicationDbContext())
using (MemoryStream stream = new MemoryStream())
using (Document doc = new Document())
using (PdfCopy pdf = new PdfCopy(doc, stream))
{
doc.Open();
PdfReader reader = null;
PdfImportedPage page = null;
db.PDFForms.Where(p => pdfs.Contains(p.Id)).ToList().ForEach(file =>
{
var filePath = Path.Combine(System.Web.Hosting.HostingEnvironment.MapPath("~/" + string.Format("Content/Uploads/PDFForms/")), file.FileName);
reader = new PdfReader(filePath);
for (int i = 0; i < reader.NumberOfPages; i++)
{
page = pdf.GetImportedPage(reader, i + 1);
pdf.AddPage(page);
}
pdf.FreeReader(reader);
reader.Close();
});
HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
result.Content = new ByteArrayContent(stream.ToArray());
result.Content.Headers.ContentType =
new MediaTypeHeaderValue(string.Format("{0}", "application/pdf"));
return result;
}
}
this is my code, however when i stream the data back to the client the browser give me the error, failed to load pdf document. Any idea what i might be doing wrong? thank you.
Edit:
This works if i create a physical file and not use MemoryStream
Perhaps you can debug your application using wireshark?
Get the bytes from the response, paste them in a document and see whether that document can be read with something like Adobe Reader.
From the looks of it though, this does not seem like an iText issue, since you have confirmed that you can create a physical file.
So either it is the implementation of MemoryStream, or some other step that comes in between the creation of the document and sending the get response.
At any rate, I think the first step in solving this problem is storing the bytes you do get back, and comparing them against the physical file.

How To Save Attachments object to RackSpace Cloud using C#?

I Have one 'System.Net.Mail.Attachment[] attachment' object , This object contains PDF,Xls,Doc or jpg file.
I want to save this attachment object to cloud server.
string sSavePath = "EmailAttachment/" + intSomeid + "/";
string strErrorMsg = string.Empty;
if ((attachments != null))
{
MemoryStream memoryStream = new MemoryStream();
StreamWriter memoryWriter = new StreamWriter(memoryStream);
memoryWriter.Write(attachments[0]);
memoryStream.Position = 0;
CloudFileSystem.SaveFileToCloudSystem(memoryStream, ref strErrorMsg, sSavePath, ConfigHelper.PrivateContainer, attachments[intI].Name);
memoryWriter.Dispose();
memoryStream.Dispose();
}
I have used the above code to save the file.
The File is saved to cloud but having 0 Byte data (Corrupted) File.
I have searched many places for that.
But not able to find error in the code.
Please suggest some solution in this case ?
Looks like you are making it yourself more difficult then needed. The Attachment instance has an ContentStream property which you don't need to feed through a MemoryStream at all.
string sSavePath = "EmailAttachment/" + intSomeid + "/";
string strErrorMsg = string.Empty;
if ((attachments != null))
{
CloudFileSystem.SaveFileToCloudSystem(
attachments[intI].ContentStream,
ref strErrorMsg,
sSavePath,
ConfigHelper.PrivateContainer,
attachments[intI].Name);
}
If you are doing this:
MemoryStream memoryStream = new MemoryStream();
StreamWriter memoryWriter = new StreamWriter(memoryStream);
memoryWriter.Write(attachments[0]);
You are probably writing the string representation of Attachment (ToString() gets called) and that is not the content of your file.
After so much r&d ,I have come up with the following answer
Memory stream of attachment object didn't work for me.
So I have approached temp path where the attachement was saved and do the following magical code :
string FileName = ((System.IO.FileStream (attachments[intI].ContentStream)).Name;
MemoryStream ms = new MemoryStream();
using (FileStream file = new FileStream(FileName, FileMode.Open, FileAccess.Read))
{
byte[] bytes = new byte[file.Length];
file.Read(bytes, 0, (int)file.Length);
ms.Write(bytes, 0, (int)file.Length);
}
ms.Position = 0;
CloudFileSystem.SaveFileToCloudSystem(ms, ref strErrorMsg, sSavePath, ConfigHelper.PrivateContainer, attachments[intI].Name);
ms.Dispose();
I hope my question and answer helps you for your project

Trying to create an in memory Word Doc with OpenXml says it's corrupt

I've built an ActionResult to output data to a Word Document. I get no errors at compile or runtime, but when trying to open the file I get the message: 'We're sorry, We can't open filename.docx because we found a problem with its contents.'.
Here's what I'm trying to do:
public override void ExecuteResult(ControllerContext context)
{
//Create a response stream to create and write the Excel file
HttpContext curContext = HttpContext.Current;
curContext.Response.Clear();
curContext.Response.AddHeader("content-disposition", "attachment;filename=text.docx");
curContext.Response.Charset = "";
curContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
curContext.Response.ContentType = "application/vnd.ms-word";
//Write the stream back to the response
var ms = new MemoryStream();
var repData = "<b>Mark's Test Book: With a Special Sub Title</b><br /><br /><b>Chapter: Chapter Title 1: Chapter Title sub</b><br /><br />";
Document.CreateAndAddHtmlToWordprocessingStream(ms, repData);
curContext.Response.OutputStream.Write(ms.GetBuffer(), 0, ms.GetBuffer().Length);
curContext.Response.End();
}
The static method is as follows:
public static void CreateAndAddHtmlToWordprocessingStream(Stream stream, string inputBody)
{
// Open a WordProcessingDocument based on a stream.
WordprocessingDocument wordprocessingDocument =
WordprocessingDocument.Create(stream, WordprocessingDocumentType.Document);
// Add a main document part.
MainDocumentPart mainPart = wordprocessingDocument.AddMainDocumentPart();
// Create the document structure.
mainPart.Document = new DocumentFormat.OpenXml.Wordprocessing.Document();
// Create the document body.
mainPart.Document.AppendChild(new Body());
var ms = new MemoryStream(System.Text.Encoding.Default.GetBytes("<html><head></head><body style=\"font-family:'Calibri';\">" + inputBody + "</body></html>"));
var altChunkId = "id";
var formatImportPart = mainPart.AddAlternativeFormatImportPart(AlternativeFormatImportPartType.Html, altChunkId);
formatImportPart.FeedData(ms);
var altChunk = new AltChunk { Id = altChunkId };
mainPart.Document.Body.Append(altChunk);
mainPart.Document.Save();
// Close the document handle.
wordprocessingDocument.Close();
// Caller must close the stream.
}
I've looked at these two posts, but didn't find anything that helped:
C# return memory stream from OpenXML resulting to a corrupted word file
Streaming In Memory Word Document using OpenXML SDK w/ASP.NET results in "corrupt" document
ms.GetBuffer() will return the automatically managed and sized buffer. This will start with the data you have written, but may contain extra \0 bytes at the end in the eventuality you continue to .Write().
To return a MemoryStream, you can use either of the following:
ms.Position = 0;
ms.CopyTo(curContext.Response.OutputStream);
or:
var msResult = ms.ToArray();
curContext.Response.OutputStream.Write(msResult, 0, msResult.Length);
you could create a method like this to handle the memory stream and the filename formatting
private static void DynaGenWordDoc(string fileName, Page page, WordprocessingDocument wdoc)
{
page.Response.ClearContent();
page.Response.ClearHeaders();
page.Response.ContentType = "application/vnd.ms-word";
page.Response.AppendHeader("Content-Disposition", string.Format("attachment;filename={0}.docx", fileName));
using (MemoryStream memoryStream = new MemoryStream())
{
wdoc.SaveAs(memoryStream);
memoryStream.WriteTo(page.Response.OutputStream);
memoryStream.Close();
}
page.Response.Flush();
page.Response.End();
}

Edit RTF as plain text but unable to open it again

I have a RTF file that I want to open, replace a String "TEMPLATE_Name" and save. But after saving, the file cannot open correctly again. When I use MS Word, the file opens and shows the RTF raw code instead the text.
I am afraid I am breaking the format or the encoding but I don't really know how:
using (MemoryStream ms = new MemoryStream(1000))
using (StreamWriter sw = new StreamWriter(ms,Encoding.UTF8))
{
using (Stream fsSource = new FileStream(Server.MapPath("~/LetterTemplates/TestTemplate.rtf"), FileMode.Open))
using (StreamReader sr = new StreamReader(fsSource,Encoding.UTF8))
while (!sr.EndOfStream)
{
String line = sr.ReadLine();
line = line.Replace("TEMPLATE_Name", model.FirstName + " " + model.LastName);
sw.WriteLine(line);
}
ms.Position = 0;
using (FileStream fs = new FileStream(Server.MapPath("~/LetterTemplates/test.rtf"), FileMode.Create))
ms.CopyTo(fs);
}
Any idea about what could be the issue?
Thanks.
SOLUTION: One problem was what #BrokenGlass has pointed out, the fact I was not flushing the stream. The other was the encoding. In the fist line of the RTF file I can see:
{\rtf1\adeflang1025\ansi\ansicpg1252\uc1\
So, even without understand anything about RTF, I set the encoding to code page 1252 and it works:
using (MemoryStream ms = new MemoryStream(1000))
using (StreamWriter sw = new StreamWriter(ms,Encoding.GetEncoding(1252)))
{
using (Stream fsSource = new FileStream(Server.MapPath("~/LetterTemplates/TestTemplate.rtf"), FileMode.Open))
using (StreamReader sr = new StreamReader(fsSource,Encoding.GetEncoding(1252)))
while (!sr.EndOfStream)
{
String line = sr.ReadLine();
line = line.Replace("TEMPLATE_Name", model.FirstName + " " + model.LastName);
sw.WriteLine(line);
}
sw.Flush();
ms.Position = 0;
using (FileStream fs = new FileStream(Server.MapPath("~/LetterTemplates/test.rtf"), FileMode.Create))
ms.CopyTo(fs);
}
StreamWriter is buffering content - make sure you call sw.Flush() before reading from your memory stream.
StreamWriter.Flush():
Clears all buffers for the current writer and causes any buffered data
to be written to the underlying stream.
Edit in light of comments:
A better alternative as #leppie alluded to is restructuring the code to use the using block to force flushing, instead of explicitly doing it:
using (MemoryStream ms = new MemoryStream(1000))
{
using (StreamWriter sw = new StreamWriter(ms,Encoding.UTF8))
{
//...
}
ms.Position = 0;
//Write to file
}
An even better alternative as #Slaks pointed out is writing to the file directly and not using a memory stream at all - unless there are other reasons you are doing this this seems to be the most straightforward solution, it would simplify your code and avoid buffering the file in memory.

Categories

Resources