Davecz
Davecz

Reputation: 1221

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

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.

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?

Upvotes: 2

Views: 11547

Answers (2)

user2567674
user2567674

Reputation: 191

Don't want to create duplicate, will post it here.. The code does not seem to work, it does attach something to the pdf though the file attachment ends up corrupted. Try on your hand, in my case with a URL:

    static void Main(string[] args)
    {
        byte[] file_bytes = File.ReadAllBytes(@"./legit.pdf");
        byte[] modified_bytes = GeneratePDFByte(file_bytes);
        File.WriteAllBytes(@"./modified.pdf", modified_bytes);
    }

    private static byte[] GeneratePDFByte(byte[] pdf_bytes)
    {
        PdfReader reader = new PdfReader(pdf_bytes);
        using (var ms = new MemoryStream())
        {
            using (PdfStamper stamper = new PdfStamper(reader, ms))
            {
                PdfFileSpecification pfs = PdfFileSpecification.Url(stamper.Writer, "https://itextpdf.com/sites/default/files/styles/max_1300x1300/public/2019-08/Octocat.png");
                stamper.AddFileAttachment("file", pfs);
            }
            reader.Close();
            return ms.ToArray();
        }
    }

This is connected to a previous post of mine (so you get the full picture): How to insert an external ressource within a PDF dcument?

Upvotes: 0

Bruno Lowagie
Bruno Lowagie

Reputation: 77528

I read:

This service return a byte array with pdf file. 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

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.

Please read the documentation. There is a handy table (6.1) that gives you an overview of the different classes and when they are to be used.

I quote the description of the PdfReader and PdfStamper class:

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).

We have established that you are doing it wrong: you should use PdfReader and PdfStamper instead of Document and PdfWriter. Now let's 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.

Please take a look at The Best iText Questions on StackOverflow for more answers.

Upvotes: 3

Related Questions