* Обновление : мне удалось заставить его работать. Я настроил небольшой виртуальный сервер только для того, чтобы ловить, если кнопка отправки что-то делает, и кажется, что она работает. Хотя по какой-то причине кнопка не видна, когда я открываю PDF с помощью Adobe Reader, но она есть и работает. В браузере это показывает нормально. Я обновил код с помощью теперь работающего кода.
У меня есть несколько PDF-файлов с заполняемыми полями формы. Теперь я хочу автоматически добавить кнопку в PDF-файлы, которая при нажатии должна представить новые и заполненные PDF-файлы. Когда это работает, он будет работать на сервере, но сейчас мне просто нужна кнопка отправки.
Эта функция уже существует в Adobe Acrobat Pro DC («Добавить кнопку отправки», https://helpx.adobe.com/acrobat/using/setting-action-buttons-pdf-forms.html).But Мне нужно сделать это с большим количеством PDF-файлов, поэтому я хочу автоматизировать ее, и янужно было бы купить дорогую лицензию. Лучший из возможных способов, который я мог бы найти, - это использовать библиотеку Java PDFBOX (https://pdfbox.apache.org/index.html).). Но я застрял с добавлением действия для кнопки.
Это мой Код, вместо того, чтобы импортировать PDF, вы можете просто создать новый, пустой. Важной является кнопка отправки:
public static void main(String[] args)
{
try
{
PDDocument pdf = PDDocument.load(inputFile);
PDAcroForm acro = pdf.getDocumentCatalog().getAcroForm();
COSDictionary cosDict1 = new COSDictionary();
COSArray buttonRect1 = new COSArray();
buttonRect1.add(new COSFloat(35)); // x1
buttonRect1.add(new COSFloat(10)); // y1
buttonRect1.add(new COSFloat(105)); // x2
buttonRect1.add(new COSFloat(30)); // y2
cosDict1.setItem(COSName.RECT, buttonRect1);
cosDict1.setItem(COSName.FT, COSName.getPDFName("Btn")); // Field
// Type
cosDict1.setItem(COSName.TYPE, COSName.ANNOT);
cosDict1.setItem(COSName.SUBTYPE, COSName.getPDFName("Widget"));
cosDict1.setItem(COSName.T, new COSString("submit"));
cosDict1.setItem(COSName.DA, new COSString("/F0 6 Tf 0 g 1 1 1 rg "));
PDPushButton button = new PDPushButton(acro);
button.getCOSObject().addAll(cosDict1);
acro.getFields().add(button);
PDAnnotationWidget widget = button.getWidgets().get(0);
PDAppearanceCharacteristicsDictionary buttonFieldAppearance = new
PDAppearanceCharacteristicsDictionary(
new COSDictionary());
COSArray borderColorArray = new COSArray();
borderColorArray.add(new COSFloat((float)(141f / 255f)));
borderColorArray.add(new COSFloat((float)(179f / 255f)));
borderColorArray.add(new COSFloat((float)(226f / 255f)));
PDColor blue = new PDColor(borderColorArray, PDDeviceRGB.INSTANCE);
buttonFieldAppearance.setBorderColour(blue);
buttonFieldAppearance.setBackground(blue);
buttonFieldAppearance.setNormalCaption("Submit");
widget.setAppearanceCharacteristics(buttonFieldAppearance);
pdf.save(outputFile);
pdf.close();
}
catch (Exception e)
{
e.printStackTrace();
System.err.println(e.getLocalizedMessage());
}
}
Даже после прочтения частей API PDFBOX (https://pdfbox.apache.org/docs/2.0.13/javadocs/) Я до сих пор не понимаю, как я должен это делать. Я пытался реверс-инжиниринг формы PDF с рабочей кнопкой отправки, которую я создал с помощью тестовой версии Adobe Acrobat Pro DC. Это сделало ее немного понятнее, но я все ещене полностью понимаю. Я заметил, что он что-то делает с COSDictonarys, поэтому я добавил следующий код, который обрабатывает действие кнопки:
PDActionSubmitForm submitForm = new PDActionSubmitForm();
widget.setAction(submitForm);
COSDictionary cosDic = new COSDictionary();
COSDictionary cosURIDic = new COSDictionary();
cosURIDic.setItem(COSName.F, new COSString("http://localhost:80/cgi-
bin/myscript#FDF"));
cosURIDic.setItem(COSName.FILESPEC, COSName.URI);
cosDic.setItem(COSName.F, cosURIDic);
cosDic.setItem(COSName.S, COSName.getPDFName("SubmitForm"));
COSDictionary buttonCOSDic = new COSDictionary(cosDic);
widget.getAction().getCOSObject().addAll(buttonCOSDic);
pdf.getPage(0).getAnnotations().add(widget);
button.getWidgets().add(widget);
И это то, что я используюd, чтобы попытаться выполнить обратный инжиниринг того, что делает Adobe Acrobat Pro DC:
public static void main(String[] args)
{
try
{
PDDocument pdf = PDDocument.load(inputFile);
PDAcroForm acro = pdf.getDocumentCatalog().getAcroForm();
List<PDField> acroFields = acro.getFields();
for (PDField pdField : acroFields)
{
if (pdField.getFullyQualifiedName().toLowerCase().contains("submit"))
{
try
{
System.out.println("FieldType: " + pdField.getFieldType());
// System.out.println("Actions: " + pdField.getActions().toString()); //NullPointer
System.out.println("Widgets: " + pdField.getWidgets().toString());
List<PDAnnotationWidget> listWidgets = pdField.getWidgets();
for (PDAnnotationWidget pdAnnotationWidget : listWidgets)
{
System.out.println("PDAction: " + pdAnnotationWidget.getAction());
System.out
.println("PDActionCOSObject: " + pdAnnotationWidget.getAction().getCOSObject());
}
}
catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
System.err.println(e.getLocalizedMessage());
}
}
}
System.out.println("end");
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
, который печатает:
FieldType: Btn
Widgets: [org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationWidget@156643d4]
PDAction: org.apache.pdfbox.pdmodel.interactive.action.PDActionSubmitForm@200a570f
PDActionCOSObject: COSDictionary{COSName{F}:COSDictionary{COSName{F}:COSString{http://localhost:80/cgi-bin/myscript#FDF};COSName{FS}:COSName{URL};};COSName{S}:COSName{SubmitForm};}
Поэтому я буду продолжать пытаться найти решение, но, возможно, некоторые из вас ужезнать ответ и может помочь мне. Надеюсь, я включил все, что тебе может понадобиться, чтобы помочь мне.