How to load a PDF from a stream and add a file attachment?

Tags: file attachmentembedded filesPdfReaderPdfStamperiText 5

I'm using a MS SQL Report Server web service to generate reports in the PDF format:

byte[] Input;
   ReportServer report = new ReportServer(
    serverUrl + @"/ReportExecution2005.asmx", reportPath);
Input = report.RenderToPDF(reportParamNames, reportParamValues);
This service returns a byte array with pdf file and I need this byte array load to iTextSharp:

using (MemoryStream ms = new MemoryStream(Input)) {
       Document doc = new Document();
       PdfWriter writer = PdfWriter.GetInstance(doc, ms);
       doc.Open();
    ...
}
This seems ok, but then I am trying to add an attachment to this PDF:

PdfFileSpecification pfs = PdfFileSpecification.FileEmbedded(writer, xmlInputFile, xmlFileDisplayName, null);
writer.AddFileAttachment(pfs);
This seems OK too, but when I save stream to file, the resulting PDF is not correct.

Note that the file attachment will always be an XML file, which I need to create in memory and never will be in file system. How can I do this with iTextSharp?

Posted on StackOverflow on Jan 29, 2015 by Davecz

I read:

This service returns a byte array with pdf file and I need this byte array load to iTextSharp:

{line-numbers=off,lang=csharp}

using (MemoryStream ms = new MemoryStream(Input))
{
    Document doc = new Document();
    PdfWriter writer = PdfWriter.GetInstance(doc, ms);
    doc.Open();
    ...
}

this seems ok

This is not OK. You want to add an attachment to an existing PDF file, however, you are using Document and PdfWriter which are classes to create a new PDF document from scratch. You need to use a combination of PdfReader and PdfStamper instead:

PdfReader: Reads PDF files. You pass an instance of this class to one of the other PDF manipulation classes.

PdfStamper: Manipulates one (and only one) PDF document. Can be used to add content at absolute positions, to add extra pages, or to fill out fields. All interactive features are preserved, except when you explicitly remove them (for instance, by flattening a form).

Please take a look at some examples:

PdfReader reader = new PdfReader(pdf_bytes);
using (var ms = new MemoryStream()) {
    using (PdfStamper stamper = new PdfStamper(reader, ms)) {
        PdfFileSpecification pfs = PdfFileSpecification.FileEmbedded(
            stamper.Writer, xmlInputFile, xmlFileDisplayName, null);
        stamper.AddFileAttachment(pfs);
    }
    reader.Close();
    return ms.ToArray();
}

As you can see, we create a PdfReader instance using the bytes that were kept in memory. We then use PdfStamper to create a new MemoryStream of which we use the bytes.