1

複数ページの 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();

PdfStamper に MemoryStream を使用し、次の行のコメントを解除する場合:

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

1 に答える 1

2

問題は、どのように機能するかについての誤解である可能性が最も高いですPdfStamperPdfReaderスタンプのデータや、そのリーダーから事前にエクスポートされたページをなんとか操作していると思われるかもしれません。これは当てはまりません。aはリーダーのデータに基づいて(出力ストリームに)新しいPDFファイルをPdfStamper生成しますが、リーダー自体のコンテンツはすべての変更を反映するように更新されません(PdfReaderオブジェクトはプロセスでタッチされる可能性があります)ただし、後で再利用することはできません)。それで...

コメントですでに述べたように、すべて同じ`FileStream'出力を書き込んでいるインスタンスPdfConcatenateと不明な数のインスタンスがあります。PdfStamperこれらのオブジェクトはそれぞれ独立したPDFを作成するため、いずれかが勝てば幸運です。少なくとも適切なPDFが出力として取得されるからです。そうしないと、例外が発生するか、複数のPDFが混在するガベージが発生します。したがって、PdfConcatenateのみを出力ファイルのターゲットにします。

テンプレートフィールドに毎回4枚のカードの内容を繰り返し入力して結果を組み合わせることが実際の目的である場合は、テンプレートのページをに追加しないでください---そのリーダーのページは入力されていません!---代わりに、PdfStamper出力をに設定し、フィールドに入力し、フォームをフラット化し、閉じ、出力を新しいで開き、そのリーダーのすべてのページをPdfConcatenateに追加します。PdfReaderPdfConcatenateMemoryStreamPdfReader

私は主にJavaを使用しており、テストされていないC#コードを書き留めると、複数のエラーが含まれる可能性が高いため、あえてコードに組み込むことはしません...;)

PS:現在、あなたはPdfReaderあなたが開いたすべてのインスタンスがどこかで暗黙的に閉じられることを期待しています。現在はそうですが、iText SVNリポジトリでの最近のチェックインは、これらの暗黙のクローズ呼び出しがコードから削除されていることを示しているようです。したがって、PdfReader使用しなくなったインスタンスを明示的に閉じることも開始してください。そうしないと、リーダーのクローズが遅すぎるために発生するメモリリークにすぐに対処する必要があります。

于 2012-11-15T09:22:11.097 に答える