iTextSharp 从字节数组列表创建 pdf

Posted

技术标签:

【中文标题】iTextSharp 从字节数组列表创建 pdf【英文标题】:iTextSharp creation of a pdf from a list of byte arrays 【发布时间】:2011-04-27 02:00:08 【问题描述】:

我有一个 byte[] 列表,我想将其连接成一个 byte[],这将是最终的 PDf。

在“page = copy.GetImportedPage(new PdfReader(p), i);”上,我得到一个“对象引用未设置为实例错误。

我不知道发生了什么,我已经检查了每个对象并且没有空值。

关于这个的任何想法,或另一段可以成功的代码?!

我有这个方法:

编辑

      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;
    

堆栈跟踪:

[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

感谢您的宝贵时间!

【问题讨论】:

我已经添加了堆栈跟踪。感谢您的宝贵时间! 只是要指出的另一件小事。因为 GetImportedPage 不是基于 0 的,所以您必须从 1 开始您的 i val。现在只需确保您的页面值 (NumberOfPages) 允许您获取所有数据。现在您似乎缺少任何 PDF 文档的最后一页。 感谢您的建议,我马上去检查,谢谢大家! 【参考方案1】:

此解决方案适用于 iText 7.1.8:

它基于以前的答案和新的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();
        
    

【讨论】:

【参考方案2】:

这行得通:

使用iTextSharp-LGPL4.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】:

我最初使用上面的答案并且 PDF 非常大。我认为返回并提供这个链接会很有帮助,它完全解决了这个问题以及我的 LARGE PDF 问题。

https://***.com/a/6752769

【讨论】:

【参考方案4】:

我已经想通了,这样每个人都可以有解决方案: 在这里:

    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;
    

希望有帮助!

【讨论】:

你是个传奇!感谢您回来分享这个金块。 遇到错误PDF header signature not found. 可以帮忙【参考方案5】:

查看 itextsharp 代码,它可能并不总是适用于同一内容的多个阅读器。

建议你试试

page = copy.GetImportedPage(reader, i);

而不是为您尝试阅读的每个页面创建一个新的阅读器。

更新:我不知道是否有帮助,但是

我复制并粘贴了您的代码,但我得到了 NullReferenceException 但仅在这一行

 stamp.AlterContents();

这很奇怪,因为那是在你得到它之后。+

当在列表中传递不良内容时,我能够产生 Missing PDF header、Trailer Not found 等,所以我认为 p 的内容没有区别

我用的是5.0.4版本,源码版本是VS 2008内置的,客户端是vs 2010的,也许这些是区别的原因。

【讨论】:

感谢您的回复,但这并没有帮助,我编辑了代码,所以这就是我现在所拥有的: PdfReader 阅读器; foreach (byte[] p in pdf) reader = new PdfReader(p); int pages = reader.NumberOfPages; // 遍历文档页面 for (int i = 0; i 我的错,我实际上修改了将 byte[] 名称从 todos 更改为 all 的代码,并且错过了它,但这不是问题。我将编辑代码并保持原样。感谢您的帮助。 我更新了我的答案以删除有关编译错误的部分,但老实说,我认为这不会有帮助。就像我说的那样,我尝试传递愚蠢的内容来尝试重现您的问题,但 iTextSharp 在面对不良内容时非常强大 这可能是问题所在。我在vs2010中使用的是4.1.2版本,我会尝试查找最新版本并试一试。感谢您的帮助,我会更新结果。【参考方案6】:

不确定这是否会为您解决问题,但请尝试从第 1 页开始初始化 GetImportedPage,不是零,而是在您的 for 循环中使用 int i = 1。像这样:

// 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);

【讨论】:

实际上是正确的,使用 GetImportedPage(reader, 0) 它会返回一个错误,但是从 1 开始页面总是给我空引用异常。我在这里迷路了,无法理解为什么。谢谢,非常感谢您的帮助!

以上是关于iTextSharp 从字节数组列表创建 pdf的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 itextsharp 从 PDF 的列表框中检索用户选择的索引?

使用 iTextSharp 创建 PDF 时放置页码

iTextSharp 创建带有空白页的 PDF

iTextSharp操作PDF

用Itextsharp 组件导出PDF 的文档的方法

iTextSharp 从现有的 PDF 模板生成 PDF