iText5.x Настройка внешнего вида кнопки без нарушения печати - PullRequest
0 голосов
/ 07 сентября 2018

Вот контекст:

  1. Мы добавляем две пустые страницы в существующий PDF, каждая из которых содержит пустое поле кнопки
  2. Мы применяем печать PAdES B-B со всеми правами на внесение изменений в документ
  3. Мы модифицируем кнопку, чтобы вставить в нее изображение

Когда мы пытаемся изменить внешний вид кнопки для установки изображения, срок действия печати нарушается с «несанкционированным изменением», независимо от того, что мы пытаемся.

Вот пример кода:

PdfReader pdfReader = new PdfReader("test.pdf");
PdfStamper pdfStamper = new PdfStamper(pdfReader, output, pdfReader.getPdfVersion(), true);

AcroFields acroFields = pdfStamper.getAcroFields();
String imageFieldId = "imageField1";
acroFields.setField(imageFieldId, Base64.encodeBytes(consentImage));

pdfStamper.close();
pdfReader.close();

Мы также попробовали с рекомендуемым способом в документации без успеха:

PushbuttonField pbField = acroFields.getNewPushbuttonFromField(imageFieldId);
pbField.setImage(Image.getInstance("image1.jpg"));
acroFields.replacePushbuttonField(imageFieldId, pbField.getField());

Проблема в том, что я не знаю, поддерживается ли этот тип модификаций iText или это наш способ изменения неправильной кнопки?

Обновление

Если сертификация заменена простой подписью, мы можем установить внешний вид кнопки, не нарушая ее.

1 Ответ

0 голосов
/ 20 сентября 2018

Почему подпись сертификации сломана

Вы говорите

Мы применяем печать PAdES B-B со всеми правами на внесение изменений в документ

, что не означает, что разрешены все мыслимые изменения документа, но вместо этого разрешены все допустимые изменения . В соответствии со спецификацией PDF возможны следующие варианты:

  1. Изменения в документе не допускаются; любое изменение в документе делает подпись недействительной.
  2. Разрешенные изменения должны заполнять формы, создавать шаблоны страниц и подписываться; другие изменения делают подпись недействительной.
  3. Допустимые изменения должны быть такими же, как для 2, а также создание, удаление и изменение аннотации; другие изменения делают подпись недействительной.

Таким образом, в случае вашего документа допустимые изменения включают заполнение форм и произвольные манипуляции с аннотациями.

К сожалению, iText 5 при установке «значения» кнопки AcroForm не просто устанавливает вид кнопки на кнопку, а вместо этого

PushbuttonField pb = getNewPushbuttonFromField(name);
pb.setImage(img);
replacePushbuttonField(name, pb.getField());

т.е. по сути заменяет прежнюю кнопку аналогичной. Это как таковое не допускается.

Почему простая подпись одобрения не сломана

Спецификация PDF не ограничивает изменения, разрешенные для документа, подписанного простой подписью утверждения (если ограничения явно не указаны в преобразовании FieldMDP).

Adobe однажды заявила, что они ограничивают изменения, разрешенные для подписанных, но не заверенных документов, например, для заверенного документа со значением ограничения 3 плюс «Добавление полей подписи», ср. этот ответ , но, очевидно, они немного слабее и в других отношениях. В частности, текущие версии Adobe Reader предупреждают только о «Полях формы с изменениями свойств» в данном случае.

Дополнительное осложнение

PDF-файл, о котором идет речь, фактически не имеет только определения формы AcroForm, вместо этого он имеет аналогичное определение формы XFA, это документ гибридной формы. Таким образом, чтобы изменить изображение в обоих определениях формы, необходимо учитывать и заполнение формы XFA.

К счастью, способ, которым iText 5 заполняет изображение в форме XFA, не заставляет Adobe Reader предполагать, что печать сломана.

Как установить изображение кнопки вместо того, чтобы не сломать печать

Чтобы не сломать печать, мы должны установить изображение кнопки, не меняя основную форму, просто виджет. Таким образом, следующий код пытается изменить только внешний вид кнопки:

PdfReader pdfReader = new PdfReader(SOURCE);
PdfStamper pdfStamper = new PdfStamper(pdfReader, TARGET, pdfReader.getPdfVersion(), true);
byte[] bytes = IMAGE_BYTES;

AcroFields acroFields = pdfStamper.getAcroFields();
String name = "mainform[0].subform_0[0].image_0_0[0]";
String value = Base64.getEncoder().encodeToString(bytes);
Image image = Image.getInstance(bytes);

XfaForm xfa = acroFields.getXfa();
if (xfa.isXfaPresent()) {
    name = xfa.findFieldName(name, acroFields);
    if (name != null) {
        String shortName = XfaForm.Xml2Som.getShortName(name);
        Node xn = xfa.findDatasetsNode(shortName);
        if (xn == null) {
            xn = xfa.getDatasetsSom().insertNode(xfa.getDatasetsNode(), shortName);
        }
        xfa.setNodeText(xn, value);
    }
}

PdfDictionary widget = acroFields.getFieldItem(name).getWidget(0);
PdfArray boxArray = widget.getAsArray(PdfName.RECT);
Rectangle box = new Rectangle(boxArray.getAsNumber(0).floatValue(), boxArray.getAsNumber(1).floatValue(), boxArray.getAsNumber(2).floatValue(), boxArray.getAsNumber(3).floatValue());

float ratioImage = image.getWidth() / image.getHeight();
float ratioBox = box.getWidth() / box.getHeight();
boolean fillHorizontally = ratioImage > ratioBox;
float width = fillHorizontally ? 1 : ratioBox / ratioImage;
float height = fillHorizontally ? ratioImage / ratioBox : 1;
float xOffset = 0; // centered: (width - 1) / 2;
float yOffset = height - 1; // centered: (height - 1) / 2;
PdfAppearance app = PdfAppearance.createAppearance(pdfStamper.getWriter(), width, height);
app.addImage(image, 1, 0, 0, 1, xOffset, yOffset);
PdfDictionary dic = (PdfDictionary)widget.get(PdfName.AP);
if (dic == null)
    dic = new PdfDictionary();
dic.put(PdfAnnotation.APPEARANCE_NORMAL, app.getIndirectReference());
widget.put(PdfName.AP, dic);
pdfStamper.markUsed(widget);

pdfStamper.close();
pdfReader.close();

( SetImageInSignedPdf test testSetInXfaAndAppearanceSampleCert)

В моих тестах это приводит к тому, что изображение становится видимым как в средствах просмотра, которые поддерживают формы XFA, так и в тех, которые его не поддерживают, а печать не считается нарушенной Adobe Reader.

Осторожно, я разработал и протестировал это только с вашим образцом документа; есть вероятность, что некоторые пограничные условия могут не учитываться.

...