itext sharp merge pdfs with acrofields - fields go

2019-07-25 12:44发布

问题:

I have tried this now and its not working. form.GenerateAppearances = true; I merge my 2 documents and then save it. Then I open it again to populate all the fields. It says all the Acrofields keys are gone but when I open it in Nitro pro its there. Why can't I see them in code? Do I have to add something before I save?

private static void CombineAndSavePdf1(string savePath, List<string> lstPdfFiles)
{
    using (Stream outputPdfStream = new FileStream(savePath, FileMode.Create, FileAccess.Write, FileShare.None))
    {
        Document document = new Document();
        PdfSmartCopy copy = new PdfSmartCopy(document, outputPdfStream);
        document.Open();
        PdfReader reader;
        int totalPageCnt;
        PdfStamper stamper;
        string[] fieldNames;
        foreach (string file in lstPdfFiles)
        {
            reader = new PdfReader(file);
            totalPageCnt = reader.NumberOfPages;
            for (int pageCnt = 0; pageCnt < totalPageCnt; )
            {
                //have to create new reader for each page or PdfStamper will throw error
                reader = new PdfReader(file);
                stamper = new PdfStamper(reader, outputPdfStream);
                fieldNames = new string[stamper.AcroFields.Fields.Keys.Count];
                stamper.AcroFields.Fields.Keys.CopyTo(fieldNames, 0);
                foreach (string name in fieldNames)
                {
                    stamper.AcroFields.RenameField(name, name);
                }

                copy.AddPage(copy.GetImportedPage(reader, ++pageCnt));

            }
            copy.FreeReader(reader);
        }
    }
}

回答1:

You are merging the documents the wrong way. See MergeForms to find out how to do it correctly. The key line that is missing in your code, is:

copy.setMergeFields();

Without it, the fields disappear (as you have noticed).

There's also a MergeForms2 example that explains how to merge two identical forms. In this case, you need to rename the fields, because each field needs to have a unique name. I'm adding a reference to this second example, because I see that you also try renaming the fields. There is, however, a serious flaw in your code: you create a stamper object, but you never do stamper.close(). Your use of the reader object is also problematic. All in all, it would be best to throw away your code, and to start anew using the two examples from the official iText web site.

Update: I've added the tags itext and itextsharp to your question. Only then I noticed that you're using iTextSharp instead of iText. Porting the Java code to C# should be easy for a C# developer, but I've never written a C# program, so please use the JAVA examples as if you were using pseudo-code. The code in C# won't be that different.

public void manipulatePdf(String src, String dest) throws IOException, DocumentException {
    Document document = new Document();
    PdfCopy copy = new PdfSmartCopy(document, new FileOutputStream(dest));
    copy.setMergeFields();
    document.open();
    List<PdfReader> readers = new ArrayList<PdfReader>();
    for (int i = 0; i < 3; ) {
        PdfReader reader = new PdfReader(renameFields(src, ++i));
        readers.add(reader);
        copy.addDocument(reader);
    }
    document.close();
    for (PdfReader reader : readers) {
        reader.close();
    }
}

public byte[] renameFields(String src, int i) throws IOException, DocumentException {
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    PdfReader reader = new PdfReader(src);
    PdfStamper stamper = new PdfStamper(reader, baos);
    AcroFields form = stamper.getAcroFields();
    Set<String> keys = new HashSet<String>(form.getFields().keySet());
    for (String key : keys) {
        form.renameField(key, String.format("%s_%d", key, i));
    }
    stamper.close();
    reader.close();
    return baos.toByteArray();
}