web-dev-qa-db-fra.com

iTextSharp création d'un pdf à partir d'une liste de tableaux d'octets

J'ai une liste d'octets [] que je voudrais concaténer en un octet [] qui sera le dernier fichier PDf. 

Sur la "page = copy.GetImportedPage (new PdfReader (p), i);" je reçois une "référence d'objet non définie à une erreur d'instance.

Je n'ai aucune idée de ce qui se passe, j'ai déjà vérifié chaque objet et il n'y a pas de null. 

Des idées sur ceci, ou un autre morceau de code qui pourrait faire l'affaire?!

J'ai cette méthode: 

MODIFIER

      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;
    }

Trace de la pile:

[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

merci pour votre temps!

16
valin077

Je l'ai compris, pour que tout le monde puisse avoir la solution: La voici:

    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;
    }

J'espère que cela pourra aider!

40
valin077

Cela marche:

utilisé 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;
        }
    }
3
Nina

J'avais initialement utilisé la réponse ci-dessus et les fichiers PDF étaient très volumineux. J'ai pensé qu'il serait utile de revenir et de proposer ce lien qui résolvait complètement ce problème, ainsi que le problème LARGE PDF.

https://stackoverflow.com/a/6752769

0
Mike Wallace

Vous ne savez pas si cela résoudra le problème pour vous, mais essayez d’initialiser GetImportedPage à partir de la page 1, non à zéro mais à l’aide de int i = 1 dans votre boucle for. Comme ça:

// 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);
}
0
Jay Riggs

En examinant le code itextsharp, il est possible qu’il ne fonctionne pas toujours bien avec plusieurs lecteurs sur le même contenu. 

Je vous suggère d'essayer

page = copy.GetImportedPage(reader, i);

plutôt que de créer un nouveau lecteur pour chaque page que vous essayez de lire.

MISE À JOUR: Je ne sais pas si ça aide mais

J'ai copié et collé votre code et je reçois une exception NullReferenceException mais uniquement sur cette ligne.

 stamp.AlterContents();

Ce qui est étrange parce que c'est après que vous l'obtenez. +

Lors de la transmission de mauvais contenus dans la liste, j'ai pu produire Missing PDF header, Trailer not found, etc., donc je ne pense pas que ce soit une différence dans le contenu de p

J'utilise la version 5.0.4 avec la version du code source construite dans VS 2008. Le client est vs 2010. Peut-être que ceux-ci expliquent la différence.

0
Conrad Frix