簡體   English   中英

PDFBox2:Acrobat 認為我在兩個簽名之間添加的注釋已修改,為什么? 以及如何解決這個問題?

[英]PDFBox2 : Acrobat consider my annotation added between two signature as modified, why ? and how to solve this?

我正在嘗試做這個用例:

  • 我從一個包含數字簽名的文檔開始(我們的提供商正在使用基於 PDFBox 的 DCC https://github.com/esig/dss...)
  • 使用 PDFBox 2.0.27 我使用增量保存添加了注釋(我使用了不同類型的注釋、自由文本、標記為文本、標記圖像……)
  • 我發送此文檔以獲得新的數字簽名

實際結果:當我用 adobe acrobat reader 打開我的文檔時,我單擊簽名面板中的全部驗證,acrobat 聲稱我的注釋已更改郵票注釋對象已正確設置並且未在另一個增量保存中提供,我沒有知道為什么 Adobe 聲稱它已更改。

Acrobat 閱讀器簽名面板 鏈接到最終的 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM