如何使用模板和连续页面将图像添加到pdf

时间:2012-11-15 00:22:25

标签: c# .net-4.0 itextsharp

我很难在多页PDF上插入图片。 要创建几个页面,我正在使用PdfConcatenate,它的工作原理。我完全可以添加模板的页面。当我尝试添加图像时,问题就开始了。它只是不加载它们。

以下是用于添加图片的代码:

        string pdfTemplate = @"Tools\template.pdf";
        string targetPdfPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), fileName + ".pdf");

        FileStream output = new FileStream(targetPdfPath, FileMode.Create);
        PdfConcatenate pdfConcatenate = new PdfConcatenate(output);

        PdfReader pdfReader = new PdfReader(pdfTemplate);
        MemoryStream memoryStream = getMemoryStream(output);
        PdfStamper pdfStamper = new PdfStamper(pdfReader, output);

        int cardIndex = 1;

        foreach (Registry reg in registries)
        {
            setFields(reg, pdfStamper, cardIndex);

            if (cardIndex == 4)
            {
                pdfConcatenate.AddPages(pdfReader);
                pdfReader = new PdfReader(pdfTemplate);
                pdfStamper = new PdfStamper(pdfReader, output);

                cardIndex = 1;
            }
            else
            {
                cardIndex++;
            }
        }

        //if (cardIndex != 1)
        //    pdfConcatenate.AddPages(pdfReader);

        //make the form no longer editable
        pdfStamper.FormFlattening = true;

        pdfStamper.Close();
        pdfReader.Close();
        //pdfConcatenate.Close();

如果使用MemoryStream for PdfStamper并取消注释这些行:

//if (cardIndex != 1)
//    pdfConcatenate.AddPages(pdfReader);
//pdfConcatenate.Close();

我得到它来添加页面,但没有图像。

知道什么是错的?

  

解决方案:(感谢@mkl)

        string pdfTemplate = @"Tools\template.pdf";
        string targetPdfPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), fileName + ".pdf");

        FileStream output = new FileStream(targetPdfPath, FileMode.Create);
        PdfConcatenate pdfConcatenate = new PdfConcatenate(output);

        PdfReader pdfReader = new PdfReader(pdfTemplate);
        MemoryStream memoryStream = new MemoryStream();
        PdfStamper pdfStamper = new PdfStamper(pdfReader, memoryStream);

        int cardIndex = 1;

        foreach (Registry reg in registries)
        {
            setFields(reg, pdfStamper, cardIndex);

            if (cardIndex == 4)
            {
                pdfStamper.FormFlattening = true;
                pdfStamper.Close();
                PdfReader tempReader = new PdfReader(memoryStream.ToArray());

                pdfConcatenate.AddPages(tempReader);

                memoryStream = new MemoryStream();
                pdfReader = new PdfReader(pdfTemplate);
                pdfStamper = new PdfStamper(pdfReader, memoryStream);

                cardIndex = 1;
            }
            else
            {
                cardIndex++;
            }
        }

        if (cardIndex != 1)
        {
            pdfStamper.FormFlattening = true;
            pdfStamper.Close();
            PdfReader tempReader = new PdfReader(memoryStream.ToArray());

            pdfConcatenate.AddPages(tempReader);

            tempReader.Close();
        }

        pdfStamper.Close();
        pdfReader.Close();
        pdfConcatenate.Close();

1 个答案:

答案 0 :(得分:2)

问题很可能是对PdfStamper如何运作的误解。您似乎认为它以某种方式操纵PdfReader标记中的数据,以及预先从该阅读器导出的页面。这是的情况,PdfStamper根据阅读器中的数据生成新的PDF文件(在其输出流中),但阅读器本身的内容未更新以反映所有更改(PdfReader对象可能会在此过程中被触及,之后不可重复使用)。所以......

正如评论中已经提到的,你有PdfConcatenate和未知数量的PdfStamper个实例都在编写相同的`FileStream'输出。由于这些对象中的每一个都创建了一个独立的PDF,如果其中一个获胜,那么你很幸运,因为那样你将得到至少一个合适的PDF作为输出。否则,您会得到一些异常或由多个混合的PDF组成的垃圾。因此,只使PdfConcatenate定位您的输出文件。

如果您的实际意图是每次使用4张卡片的内容重复填充模板字段并合并结果,则应添加模板PdfReader中的页面到PdfConcatenate ---该读者的页面没有填写! ---但是将PdfStamper输出到MemoryStream,填充其字段,展平其形式,关闭它,在新的PdfReader中打开其输出,并将该读取器中的所有页面添加到PdfConcatenate。

我不敢把它放到代码中,因为我主要使用Java并写下未经测试的C#代码,最有可能包含多个错误......;)

PS:目前,您依靠打开的所有PdfReader个实例在某处隐式关闭。虽然目前情况属实,但最近在iText SVN存储库中的签到似乎表明这些隐式关闭调用已从代码中删除。因此,请开始明确关闭您不再使用的PdfReader个实例。否则你很快就会因为读者关闭太晚而不得不处理内存泄漏问题。