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

Tags: file attachmentembedded filesPdfReaderiText 7

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

In iText 7 this can be done in the following way:

IRandomAccessSource source = new RandomAccessSourceFactory().createSource(pdf_bytes.toByteArray());
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PdfDocument pdfDoc = new PdfDocument(new PdfReader(source, new ReaderProperties()), new PdfWriter(baos));
 
byte[] xmlInputFile;
String xmlFileDisplayName;
PdfFileSpec pfs;
for (String s : ATTACHMENTS) {
    xmlInputFile = String.format("Some test: %s", s).getBytes();
    xmlFileDisplayName = String.format("%s.xml", s);
    pfs = PdfFileSpec.createEmbeddedFileSpec(pdfDoc,
                xmlInputFile, null, xmlFileDisplayName, null, null, null, true);
    pdfDoc.addFileAttachment(xmlFileDisplayName, pfs);
}
pdfDoc.close();

As you see, we create a PdfDocument instance using the bytes that were kept in memory (pdf_bytes). We then add five file attachments. ATTACHMENTS is the array of Strings:

public static final String[] ATTACHMENTS = {"hello", "world", "what", "is", "up"};

If you need to return a byte array, try this:

return baos.toByteArray();

Click this link if you want to see how to answer this question in iText 5.