Merge memorystreams to one iText document
The error PDF header signature not found
can be fixed in this case by setting the stream's Position
back to 0
. Since you're not getting the error Cannot access a closed Stream
I'm assuming that you are already correctly setting the PdfWriter
's CloseStream
to false
.
Below is a full working C# 2010 WinForm app targeting iTextSharp 5.1.1.0 that creates three PDFs in MemoryStreams
and combines them. Since I don't have a web server handy I'm writing them to disk.
using System;
using System.Text;
using System.Windows.Forms;
using System.IO;
using iTextSharp.text;
using iTextSharp.text.pdf;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
//Create three MemoryStreams
MemoryStream[] streams = { CreateDoc("Page 1"), CreateDoc("Page 2"), CreateDoc("Page 3") };
//I don't have a web server handy so I'm going to write my final MemoryStream to a byte array and then to disk
byte[] bytes;
//Create our final combined MemoryStream
using (MemoryStream finalStream = new MemoryStream())
{
//Create our copy object
PdfCopyFields copy = new PdfCopyFields(finalStream);
//Loop through each MemoryStream
foreach (MemoryStream ms in streams)
{
//Reset the position back to zero
ms.Position = 0;
//Add it to the copy object
copy.AddDocument(new PdfReader(ms));
//Clean up
ms.Dispose();
}
//Close the copy object
copy.Close();
//Get the raw bytes to save to disk
bytes = finalStream.ToArray();
}
//Write out the file to the desktop
string outputFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "Combined.pdf");
using (FileStream fs = new FileStream(outputFile, FileMode.Create, FileAccess.Write, FileShare.None))
{
fs.Write(bytes, 0, bytes.Length);
}
this.Close();
}
/// <summary>
/// Helper method to create temporary documents
/// </summary>
private MemoryStream CreateDoc(string name)
{
MemoryStream ms = new MemoryStream();
using (Document doc = new Document(PageSize.LETTER))
{
using (PdfWriter writer = PdfWriter.GetInstance(doc, ms))
{
writer.CloseStream = false;
doc.Open();
doc.Add(new Paragraph(name));
doc.Close();
}
}
return ms;
}
}
}
Johan
Updated on June 20, 2022Comments
-
Johan almost 2 years
I have four MemoryStreams of data that I want to merge and then open the pdfDocument, without creating a single file.
It's possible to write them down to files and then merge them but that would be bad practice and that can also cause a few issues so I want to avoid that.
However, I can not find a way to merge the MemoryStreams with iText5 for .NET.
Right now, this is how I do it with files:
private static void ConcatenateDocuments() { var stream = new MemoryStream(); var readerFrontPage = new PdfReader(Folder + FrontPageName); var readerDocA = new PdfReader(Folder + docA); var readerDocB = new PdfReader(Folder + DocB); var readerAppendix = new PdfReader(Folder + Appendix); var pdfCopyFields = new PdfCopyFields(stream); pdfCopyFields.AddDocument(readerFrontPage); pdfCopyFields.AddDocument(readerDocA ); pdfCopyFields.AddDocument(readerDocB); pdfCopyFields.AddDocument(readerAppendix); pdfCopyFields.Close(); SavePdf(stream, FilenameReport); }
Since I need to remove the use of files, I keep the MemoryStream's as the different parts are built from different resources. So I have references to these memorystreams.
How can this be done?
-
Leniel Maccaferri over 11 yearsPerfect. In my case I was doing
stream.Position = 0
but in the wrong place: inside theusing
statement. After moving it outside it works great. By the way Chris: congrats for helping the community when it comes to iTextSharp. God bless you! :) -
Toft almost 10 yearsThanks, working for me when remembering to set CloseStream to false on writer and call close document before using stream.
-
Standage almost 9 yearsHow would you open the pdf rather than saving to the desktop in your example?
-
Chris Haas almost 9 years@Standage, are you using a webserver? If so you could just write the bytes out. If you are on a desktop you can write the bytes out and call
System.Diagnostics.Process.Start()
on the file and as long as there is a handler registered it should open. It is very important to note that iTextSharp is in no way a PDF renderer or viewer. If you want to actually "look" at a PDF you'll need a program like Adobe Reader. -
Standage almost 9 yearsI think most users have Adobe reader these days? I got my deisred results by passing the finalStream into a new method and using 'Response.OutputStream', thanks
-
Chris Haas almost 9 yearsI would say less people (as a percentage) have Adobe Reader installed these days compared to just a couple of years ago. Mac OSX has had Preview for years which can read PDFs and Windows 8 shipped with a built-in one, too. All major modern web browsers also ship with a native PDF renderer, too. I still find it funny whenever I see a website that uses the "Adobe Reader" icon to signify a PDF. But if you just mean that most people have a PDF renderer of some sort installed, not necessarily Adobe's, I think I'd agree with that.
-
Prateju Patil about 7 yearsChris, I used your solution Today in my application and it worked wonders for me ....