Pdf itext7 java如何使用相同的/AP和/V添加多重签名字段

Pdf itext7 java如何使用相同的/AP和/V添加多重签名字段,pdf,itext7,Pdf,Itext7,我是IText7的新手,花了我两天的时间 生成pdf时,它有3个页面,如 附加: 在com.itextpdf.signatures.PdfSigner.preClose()方法中,我尝试了以下代码,虽然成功地添加了所需的对象,但只有首先添加的小部件注释才能显示在Adobe Reader中,我该怎么办 如果(字段存在)。。。否则{ PdfDictionary ap=新的PdfDictionary(); 对于(inti=1;我在你的“like…”您有三个AcroForm签名字段对象,每个对象都有一

我是IText7的新手,花了我两天的时间

生成pdf时,它有3个页面,如

附加:

在com.itextpdf.signatures.PdfSigner.preClose()方法中,我尝试了以下代码,虽然成功地添加了所需的对象,但只有首先添加的小部件注释才能显示在Adobe Reader中,我该怎么办

如果(字段存在)。。。否则{
PdfDictionary ap=新的PdfDictionary();

对于(inti=1;我在你的“like…”您有三个AcroForm签名字段对象,每个对象都有一个合并的widget注释,共享相同的字段名。因此,这三个对象表示同一抽象签名表单字段的三个widget。但是由于ISO 32000-2签名表单字段可能没有多个widget。因此,严格来说,您的构造是无效的。您认为我想这样吗?当我修改代码以实现此行为时,我发现尽管对象已成功添加,但它不能全部显示在Adobe Reader上,因为这三个字段的名称相同。请查看补充。我如何修复它?“它不能全部显示在Adobe Reader上,因为这三个字段的名称相同。请查看附录。我如何修复它?”?"-好的,由于使用相同的名称也会导致其他问题,请参阅我的第一条评论,解决方法是使用不同的名称。我从一开始就犯了一个错误,事实上我真正想要的是一次生成一个AcroForm签名字段,但每页添加一个小部件注释。可以做到吗?我注意到使用TreeMap索引的/P对象如果您违反规则,您将生成无效的PDF。当前的Adobe Acrobat版本可能仍会接受这些规则,但不能保证它们会继续这样做。(Adobe十多年来一直告诉人们,签名字段不能有多个小部件,因此如果他们开始强制执行,任何人都不应该感到惊讶。)此外,还有其他PDF签名验证器,现在可能已经提出抗议。在你的“喜欢…”您有三个AcroForm签名字段对象,每个对象都有一个合并的widget注释,共享相同的字段名。因此,这三个对象表示同一抽象签名表单字段的三个widget。但是由于ISO 32000-2签名表单字段可能没有多个widget。因此,严格来说,您的构造是无效的。您认为我想这样吗?当我修改代码以实现此行为时,我发现尽管对象已成功添加,但它不能全部显示在Adobe Reader上,因为这三个字段的名称相同。请查看补充。我如何修复它?“它不能全部显示在Adobe Reader上,因为这三个字段的名称相同。请查看附录。我如何修复它?”?"-好的,由于使用相同的名称也会导致其他问题,请参阅我的第一条评论,解决方法是使用不同的名称。我从一开始就犯了一个错误,事实上我真正想要的是一次生成一个AcroForm签名字段,但每页添加一个小部件注释。可以做到吗?我注意到使用TreeMap索引的/P对象如果您违反规则,您将生成无效的PDF。当前的Adobe Acrobat版本可能仍会接受这些规则,但不能保证它们会继续这样做。(Adobe十多年来一直告诉人们,签名字段不能有多个小部件,因此,如果他们开始强制执行,任何人都不应该感到惊讶。)此外,还有其他PDF签名验证器,如今可能会提出抗议。
4 0 obj
<</Contents 5 0 R/MediaBox[0 0 595 842]/Parent 2 0 R/Resources<</Font<</F1 6 0 R>>>>/TrimBox[0 0 595 842]/Type/Page>>
endobj
7 0 obj
<</Contents 8 0 R/MediaBox[0 0 595 842]/Parent 2 0 R/Resources<</Font<</F1 6 0 R>>>>/TrimBox[0 0 595 842]/Type/Page>>
endobj
9 0 obj
<</Contents 10 0 R/MediaBox[0 0 595 842]/Parent 2 0 R/Resources<</Font<</F1 6 0 R>>>>/TrimBox[0 0 595 842]/Type/Page>>
endobj
1 0 obj
<</AcroForm 11 0 R/Pages 2 0 R/Type/Catalog>>
endobj
9 0 obj
<</Annots[13 0 R]/Contents 10 0 R/MediaBox[0 0 595 842]/Parent 2 0 R/Resources<</Font<</F1 6 0 R>>>>/TrimBox[0 0 595 842]/Type/Page>>
endobj
11 0 obj
<</Fields[13 0 R]/SigFlags 3>>
endobj
13 0 obj
<</AP<</N 18 0 R>>/F 132/FT/Sig/P 9 0 R/Rect[280.5 810 314.5 842]/Subtype/Widget/T(sig)/V 12 0 R>>
endobj
4 0 obj
<</Annots[13 0 R]/Contents 5 0 R/MediaBox[0 0 595 842]/Parent 2 0 R/Resources<</Font<</F1 6 0 R>>>>/TrimBox[0 0 595 842]/Type/Page>>
endobj
7 0 obj
<</Annots[14 0 R]/Contents 8 0 R/MediaBox[0 0 595 842]/Parent 2 0 R/Resources<</Font<</F1 6 0 R>>>>/TrimBox[0 0 595 842]/Type/Page>>
endobj
9 0 obj
<</Annots[15 0 R]/Contents 10 0 R/MediaBox[0 0 595 842]/Parent 2 0 R/Resources<</Font<</F1 6 0 R>>>>/TrimBox[0 0 595 842]/Type/Page>>
endobj
13 0 obj
<</AP<</N 18 0 R>>/F 132/FT/Sig/P 4 0 R/Rect[280.5 810 314.5 842]/Subtype/Widget/T(sig)/V 12 0 R>>
endobj
14 0 obj
<</AP<</N 18 0 R>>/F 132/FT/Sig/P 7 0 R/Rect[200 400 300 420]/Subtype/Widget/T(sig)/V 12 0 R>>
endobj
15 0 obj
<</AP<</N 18 0 R>>/F 132/FT/Sig/P 9 0 R/Rect[100 200 150 480]/Subtype/Widget/T(sig)/V 12 0 R>>
endobj
11 0 obj
<</Fields[13 0 R 14 0 R 15 0 R]/SigFlags 3>>
endobj
PdfDocument pdfDocument = new PdfDocument(new PdfReader(FILE));
final int pageCount = pdfDocument.getNumberOfPages();
pdfDocument.close();

PdfReader pdfReader = new PdfReader(FILE);
PdfSigner pdfSigner = new PdfSigner(pdfReader, new FileOutputStream(SIGN), new StampingProperties().useAppendMode());

File imageFile = new File(IMAGE);
java.awt.Image image = ImageIO.read(imageFile);
ImageData imageData = ImageDataFactory.create(image, null);
Rectangle rect = new Rectangle(
    (pdfDocument.getDefaultPageSize().getRight() / 2) - (imageData.getWidth() / 2),
    pdfDocument.getDefaultPageSize().getTop() - imageData.getHeight(),
    imageData.getWidth(),
    imageData.getHeight()
);

PdfSignatureAppearance appearance = pdfSigner.getSignatureAppearance();
appearance.setPageNumber(pageCount);
appearance.setSignatureGraphic(imageData);
appearance.setRenderingMode(PdfSignatureAppearance.RenderingMode.GRAPHIC);
appearance.setPageRect(rect);
appearance.setReason("reason");
appearance.setLocation("location");
appearance.setReuseAppearance(false);

pdfSigner.setFieldName("sig");

KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(new FileInputStream(KEYSTORE), PASSWORD);
String alias = ks.aliases().nextElement();
PrivateKey pk = (PrivateKey) ks.getKey(alias, PASSWORD);
Certificate[] chain = ks.getCertificateChain(alias);

BouncyCastleProvider provider = new BouncyCastleProvider();
Security.addProvider(provider);

IExternalSignature pks = new PrivateKeySignature(pk, DigestAlgorithms.SHA256, provider.getName());
IExternalDigest digest = new BouncyCastleDigest();

pdfSigner.signDetached(digest, pks, chain, null, null, null, 0, PdfSigner.CryptoStandard.CMS);
if (fieldExist) ... else {
    PdfDictionary ap = new PdfDictionary();
    for (int i = 1; i <= document.getNumberOfPages(); i++) {
        PdfWidgetAnnotation widget = new PdfWidgetAnnotation(appearance.getPageRect());
        widget.setFlags(PdfAnnotation.PRINT | PdfAnnotation.LOCKED);

        PdfSignatureFormField sigField = PdfFormField.createSignature(document);
        sigField.setFieldName(name);
        sigField.put(PdfName.V, cryptoDictionary.getPdfObject());
        sigField.addKid(widget);

        if (this.fieldLock != null) {
            this.fieldLock.getPdfObject().makeIndirect(document);
            sigField.put(PdfName.Lock, this.fieldLock.getPdfObject());
            fieldLock = this.fieldLock;
        }

        widget.setPage(document.getPage(i));
        widget.put(PdfName.AP, ap);
        if (1 == i)
            ap.put(PdfName.N, appearance.getAppearance().getPdfObject());

        acroForm.addField(sigField, document.getPage(i));
    }
    
    ...
    
}