![](/img/trans.png)
[英]pdfBox - Signature validity checkmark not visible in Acrobat reader
[英]PDFBox2 : Acrobat consider my annotation added between two signature as modified, why ? and how to solve this?
我正在嘗試做這個用例:
實際結果:當我用 adobe acrobat reader 打開我的文檔時,我單擊簽名面板中的全部驗證,acrobat 聲稱我的注釋已更改郵票注釋對象已正確設置並且未在另一個增量保存中提供,我沒有知道為什么 Adobe 聲稱它已更改。
鏈接到最終的 PDF: https ://drive.google.com/file/d/1CV7lJ8dY1gDcx3rgHoW5yHJ612JSAK9B/view?usp=share_link
預期結果:當我在 acrobat 中打開文檔時,我可以看到注釋,在簽名面板中一切都是綠色的,即使在單擊“驗證所有”后,注釋也沒有標記為已修改
這是代碼源:
import org.apache.pdfbox.pdmodel.PDAppearanceContentStream;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDResources;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.font.PDFont;
import org.apache.pdfbox.pdmodel.font.PDType1Font;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotation;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationRubberStamp;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAppearanceDictionary;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAppearanceStream;
import org.apache.pdfbox.util.Matrix;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.List;
public class PDFAnnotStampText {
public static void main(String[] args) {
//Creating PDF document object
PDDocument document = null;
String filename = "20221217-VisibleSign-BeforeAnnot-02";
try {
document = PDDocument.load(new File("testfiles/" + filename + ".pdf"));
document.getClass();
if (!document.isEncrypted()) {
System.out.println("not encrypted");
// https://stackoverflow.com/questions/65927280/annotation-content-not-appearing-with-pdfbox
OutputStream resultFile = new FileOutputStream("testfiles/" + filename + "_stamptxt.pdf");
PDPage page = (PDPage) document.getPage(0);
addAnnotation("annotation name", document, page, 50, 500, "Annot powered");
document.saveIncremental(resultFile);
document.close();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private static void addAnnotation(String name, PDDocument doc, PDPage page, float x, float y, String text) throws IOException {
List<PDAnnotation> annotations = page.getAnnotations();
PDAnnotationRubberStamp t = new PDAnnotationRubberStamp();
t.setAnnotationName(name); // might play important role
t.setPrinted(true); // always visible
t.setReadOnly(true); // does not interact with user
t.setContents(text);
// calculate realWidth, realHeight according to font size (e.g. using _font.getStringWidth(text))
float realWidth = 100, realHeight = 15;
PDRectangle rect = new PDRectangle(x, y, realWidth, realHeight);
t.setRectangle(rect);
PDAppearanceDictionary ap = new PDAppearanceDictionary();
ap.setNormalAppearance(createAppearanceStream(doc, t));
t.setAppearance(ap);
annotations.add(t);
page.setAnnotations(annotations);
// these must be set for incremental save to work properly (PDFBOX < 3.0.0 at least?)
ap.getCOSObject().setNeedToBeUpdated(true);
t.getCOSObject().setNeedToBeUpdated(true);
page.getResources().getCOSObject().setNeedToBeUpdated(true);
page.getCOSObject().setNeedToBeUpdated(true);
doc.getDocumentCatalog().getPages().getCOSObject().setNeedToBeUpdated(true);
doc.getDocumentCatalog().getCOSObject().setNeedToBeUpdated(true);
}
private static void modifyAppearanceStream(PDAppearanceStream aps, PDAnnotation ann) throws IOException {
PDAppearanceContentStream apsContent = null;
try {
PDRectangle rect = ann.getRectangle();
rect = new PDRectangle(0, 0, rect.getWidth(), rect.getHeight()); // need to be relative - this is mega important because otherwise it appears as if nothing is printed
aps.setBBox(rect); // set bounding box to the dimensions of the annotation itself
// embed our unicode font (NB: yes, this needs to be done otherwise aps.getResources() == null which will cause NPE later during setFont)
PDResources res = new PDResources();
PDFont font = PDType1Font.HELVETICA_BOLD;
res.add(font).getName(); // okay I create _font elsewhere
aps.setResources(res);
// draw directly on the XObject's content stream
apsContent = new PDAppearanceContentStream(aps);
apsContent.beginText();
apsContent.setFont(PDType1Font.HELVETICA_BOLD, 12); // _font
apsContent.setTextMatrix(Matrix.getTranslateInstance(0, 1));
apsContent.showText(ann.getContents());
apsContent.endText();
}
finally {
if (apsContent != null) {
try {
apsContent.close();
} catch (Exception ex) {
System.out.println(ex);
}
}
}
aps.getResources().getCOSObject().setNeedToBeUpdated(true);
aps.getCOSObject().setNeedToBeUpdated(true);
}
private static PDAppearanceStream createAppearanceStream(final PDDocument document, PDAnnotation ann) throws IOException
{
PDAppearanceStream aps = new PDAppearanceStream(document);
modifyAppearanceStream(aps, ann);
return aps;
}
}
正如評論中所說,Adobe 簽名的 PDF(謝謝 Dimitar)在最后一次增量保存中包含了圖章注釋(DSS 簽名的 PDF 沒有)並添加了兩件事:1) /P 14 0 R
和 2) /NM (495f9a95-136e-4992-881a-6a834fa85519)
。 也許 Adobe 自己悄悄地添加了這些,然后抱怨自己的行為,盡管這兩個條目都是可選的。
在問題的代碼中調用t.setPage(page)
解決了問題。
我還在這個半官方網站上提交了錯誤報告。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.