19

I've got a list of byte[] which i'd like to concatenate into one byte[] which will be the final PDf.

On the "page = copy.GetImportedPage(new PdfReader(p), i); " i'm getting an "object reference not set to an instance error.

I've got no clue of what's going on, i've already checked every object and there's no null.

Any ideas on this, or another piece of code that could make the trick?!

I've got this method:

EDIT

      public static byte[] concatAndAddContent(List<byte[]> pdf)
    {
        byte [] todos;

        using(MemoryStream ms = new MemoryStream())
        {
            Document doc = new Document();
            doc.Open();

            PdfCopy copy = new PdfCopy(doc, ms);
            PdfCopyFields copy2 = new PdfCopyFields(ms);


            PdfReader reader;
            foreach (byte[] p in pdf)
            {
                reader = new PdfReader(p);
                int pages = reader.NumberOfPages;

                // loop over document pages
                for (int i = 1; i < pages; i++)
                {
                    PdfImportedPage page = copy.GetImportedPage(reader, i);
                    PdfCopy.PageStamp stamp = copy.CreatePageStamp(page);
                    PdfContentByte cb = stamp.GetUnderContent();
                    cb.SaveState();
                    stamp.AlterContents();
                    copy.AddPage(page);
                }
            }

            doc.Close();
            todos = ms.GetBuffer();
            ms.Flush();
            ms.Dispose();
        }

        return todos;
    }

Stack Trace:

[NullReferenceException: Object reference not set to an instance of an object.]
   iTextSharp.text.pdf.PdfImportedPage..ctor(PdfReaderInstance readerInstance, PdfWriter writer, Int32 pageNumber) +45
   iTextSharp.text.pdf.PdfReaderInstance.GetImportedPage(Int32 pageNumber) +175
   iTextSharp.text.pdf.PdfCopy.GetImportedPage(PdfReader reader, Int32 pageNumber) +256
   SAM.Web.Classes.UtileriasReportes.concatAndAddContent(List`1 pdf) in \Classes\UtileriasReportes.cs:199
   SAM.Web.Classes.UtileriasReportes.ObtenReporteOdt(Int32 ordenTrabajoID, Boolean caratula, Boolean juntas, Boolean cortes, Boolean materiales, Boolean resumenMateriales) 

in D:\MIMOSS\Desarrollo\SAM 2.0\Desarrollo\WebSolution\SAM.Web\Classes\UtileriasReportes.cs:168
   SAM.Web.Produccion.PopupImpresionOdt.btnImprimir_Click(Object sender, EventArgs e) in \PopupImpresionOdt.aspx.cs:44
   System.Web.UI.WebControls.Button.OnClick(EventArgs e) +118
   System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument) +112
   System.Web.UI.WebControls.Button.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument) +10
   System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) +13
   System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData) +36
   System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +5563

thanks for your time!

3
  • i've added the stacktrace. Thanks for your time! Commented Oct 18, 2010 at 19:36
  • Just another small thing to point out. Because GetImportedPage isn't 0 based, you had to start your i val at 1. Just make sure now that your pages value (NumberOfPages) allows you to get all of your data. Right now you seem to be missing the final page of any PDF document. Commented Oct 19, 2010 at 15:59
  • Thanks for your advice, i'll check on it right away, thanks to all! Commented Oct 19, 2010 at 19:19

6 Answers 6

49

I've figured it out, just so everbody can have the solution: here it is:

    public static byte[] concatAndAddContent(List<byte[]> pdf)
    {
        byte [] all;

        using(MemoryStream ms = new MemoryStream())
        {
            Document doc = new Document();

            PdfWriter writer = PdfWriter.GetInstance(doc, ms);

            doc.SetPageSize(PageSize.LETTER);
            doc.Open();
            PdfContentByte cb = writer.DirectContent;
            PdfImportedPage page;

            PdfReader reader;
            foreach (byte[] p in pdf)
            {
                reader = new PdfReader(p);
                int pages = reader.NumberOfPages;

                // loop over document pages
                for (int i = 1; i <= pages; i++)
                {
                    doc.SetPageSize(PageSize.LETTER);
                    doc.NewPage();
                    page = writer.GetImportedPage(reader, i);
                    cb.AddTemplate(page, 0, 0);
                }
            }

            doc.Close();
            all = ms.GetBuffer();
            ms.Flush();
            ms.Dispose();
        }

        return all;
    }

Hope that helps!

Sign up to request clarification or add additional context in comments.

2 Comments

You'r a legend! Thanks for coming back to share this nugget.
Getting an error PDF header signature not found. can some one help
4

This works:

used iTextSharp-LGPL 4.1.6:

    public static byte[] ConcatenatePdfs(IEnumerable<byte[]> documents)
    {
        using (var ms = new MemoryStream())
        {
            var outputDocument = new Document();
            var writer = new PdfCopy(outputDocument, ms);
            outputDocument.Open();

            foreach (var doc in documents)
            {
                var reader = new PdfReader(doc);
                for (var i = 1; i <= reader.NumberOfPages; i++)
                {
                    writer.AddPage(writer.GetImportedPage(reader, i));
                }
                writer.FreeReader(reader);
                reader.Close();
            }

            writer.Close();
            outputDocument.Close();
            var allPagesContent = ms.GetBuffer();
            ms.Flush();

            return allPagesContent;
        }
    }

Comments

2

This solution works in iText 7.1.8:

It is based in previous answers and the new API Examples

    public static byte[] MergePDFs(List<byte[]> lPdfByteContent)
    {
        using (MemoryStream oMemoryStream = new MemoryStream())
        {
            using (PdfWriter oWriter = new PdfWriter(oMemoryStream))
            {
                oWriter.SetSmartMode(true);

                using (PdfDocument oMergedPdf = new PdfDocument(oWriter))
                {
                    PdfMerger oMerger = new PdfMerger(oMergedPdf, false, false);

                    for (int i = 0; i < lPdfByteContent.Count; i++)
                    {
                        PdfDocument oPdfAux = new PdfDocument(new PdfReader(new MemoryStream(lPdfByteContent[i])));
                        oMerger.SetCloseSourceDocuments(true).Merge(oPdfAux, 1, oPdfAux.GetNumberOfPages());
                    }
                }
            }
            return oMemoryStream.ToArray();
        }
    }

Comments

0

Not sure if this will fix it for you, but try initializing GetImportedPage starting at page 1, not zero but usng int i = 1 in your for loop. Like this:

// loop over document pages 
//was (int i = 0; i < pages; i++) {
for (int i = 1; i < pages; i++) {
    page = copy.GetImportedPage(new PdfReader(p), i);
    stamp = copy.CreatePageStamp(page);
    PdfContentByte cb = stamp.GetUnderContent();
    cb.SaveState();
    stamp.AlterContents();
    copy.AddPage(page);
}

1 Comment

actually thats correct, using the GetImportedPage(reader, 0) it returns an error, but starting the page at 1 keeps giving me the null reference exception. i'm lost here, can't understang why. Thanks, I really appreciate your help!
0

Looking though the itextsharp code its possible that it doesn't always work well with multiple readers on the same content.

I suggest you try

page = copy.GetImportedPage(reader, i);

rather than create a new reader for each page you're trying to read.

UPDATE: I don't know if the helps but

I copied and pasted your code and I get a NullReferenceException but only on this line

 stamp.AlterContents();

Which is strange because that's after where you are getting it.+

When passing in bad contents in the List I was able to produce Missing PDF header, Trailer Not found etc., so I don't think its a difference in the content of p

I'm using version 5.0.4 with the source code version built in VS 2008. The client is vs 2010. Perhaps these account for the difference.

6 Comments

Thanks for your reply, but that didn't help, I edited the code so this is what i have right now:
PdfReader reader; foreach (byte[] p in pdf) { reader = new PdfReader(p); int pages = reader.NumberOfPages; // loop over document pages for (int i = 0; i < pages;) { PdfImportedPage page = copy.GetImportedPage(reader, ++i);
my bad, i actually modified the code changing the byte[] name from todos to all, and missed it, but thats not the problem. I'll edit the code and leave it just as I have it right now. Thanks for your help.
I updated my answer to remove the bits about compile errors, but I honestly don't think it will help. Like I said I tried passing in goofy content to try and reproduce your issue but iTextSharp is pretty robust in the face of bad content
Well that might be the problem. I'm using version 4.1.2 in vs2010, i'll try and look up for the newest version and give it a try. Thanks for your help, i'll update on the results.
|
0

I had initially used the answer above and the PDF's were very large.. I thought it would be helpful to come back and offer up this link which completely solved this issue along with the LARGE PDF issue for me.

https://stackoverflow.com/a/6752769

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.