IText объединяет документы с акрополями

В настоящее время у меня есть PdfReader и PdfStamper, которыми я заполняю поля. Теперь мне нужно скопировать другой PDF-файл в конец той формы, которую я заполнял, и когда я это сделаю, я теряю акрополь новой формы, которую я копирую. Вот код

public static void addSectionThirteenPdf(PdfStamper stamper, Rectangle pageSize, int pageIndex){
     PdfReader reader = new PdfReader(FacesContext.getCurrentInstance().getExternalContext().getResourceAsStream("/resources/documents/Section13.pdf"));
     AcroFields fields = reader.getAcroFields();

     fields.renameField("SecurityGuidancePage3", "SecurityGuidancePage" + pageIndex);

     stamper.insertPage(pageIndex, pageSize);
     stamper.replacePage(reader, 1, pageIndex);
}

То, как я создаю оригинальный документ, выглядит следующим образом.

     OutputStream output = FacesContext.getCurrentInstance().getExternalContext().getResponseOutputStream();

     PdfReader pdfTemplate = new PdfReader(FacesContext.getCurrentInstance().getExternalContext().getResourceAsStream("/resources/documents/dd254.pdf"));

     PdfStamper stamper = new PdfStamper(pdfTemplate, output);
     stamper.setFormFlattening(true);

     AcroFields fields = stamper.getAcroFields();

Есть ли способ слияния с использованием первой части кода и слияния обоих акрополей вместе?

1 ответ

Решение

В зависимости от того, что именно вы хотите, возможны разные сценарии, но в любом случае: вы делаете это неправильно. Вы должны использовать либо PdfCopy или же PdfSmartCopy объединить документы.

Различные сценарии описаны в следующем видеоуроке.

Вы можете найти большинство примеров в песочнице iText.

Объединение разных форм (с разными полями)

Если вы хотите объединить различные формы без их выравнивания, вы должны использовать PdfCopy как это делается в примере MergeForms:

public void createPdf(String filename, PdfReader[] readers) throws IOException, DocumentException {
    Document document = new Document();
    PdfCopy copy = new PdfCopy(document, new FileOutputStream(filename));
    copy.setMergeFields();
    document.open();
    for (PdfReader reader : readers) {
        copy.addDocument(reader);
    }
    document.close();
    for (PdfReader reader : readers) {
        reader.close();
    }
}

В этом случае, readers это массив PdfReader экземпляры, содержащие разные формы (с разными именами полей), поэтому мы используем PdfCopy и мы уверены, что мы не забываем использовать setMergeFields() метод, иначе поля не будут скопированы.

Объединение одинаковых форм (с одинаковыми полями)

В этом случае нам нужно переименовать поля, потому что мы, вероятно, хотим разные значения на разных страницах. В PDF поле может иметь только одно значение. Если вы объединяете идентичные формы, у вас есть несколько визуализаций одного и того же поля, но каждая визуализация будет показывать одно и то же значение (потому что в действительности есть только одно поле).

Давайте посмотрим на пример MergeForms2:

public void manipulatePdf(String src, String dest) throws IOException, DocumentException {
    Document document = new Document();
    PdfCopy copy = new PdfSmartCopy(document, new FileOutputStream(dest));
    copy.setMergeFields();
    document.open();
    List<PdfReader> readers = new ArrayList<PdfReader>();
    for (int i = 0; i < 3; ) {
        PdfReader reader = new PdfReader(renameFields(src, ++i));
        readers.add(reader);
        copy.addDocument(reader);
    }
    document.close();
    for (PdfReader reader : readers) {
        reader.close();
    }
}

public byte[] renameFields(String src, int i) throws IOException, DocumentException {
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    PdfReader reader = new PdfReader(src);
    PdfStamper stamper = new PdfStamper(reader, baos);
    AcroFields form = stamper.getAcroFields();
    Set<String> keys = new HashSet<String>(form.getFields().keySet());
    for (String key : keys) {
        form.renameField(key, String.format("%s_%d", key, i));
    }
    stamper.close();
    reader.close();
    return baos.toByteArray();
}

Как видите, renameFields() Метод создает новый документ в памяти. Этот документ объединяется с другими документами, используя PdfSmartCopy, Если бы вы использовали PdfCopy здесь ваш документ будет раздут (как мы скоро узнаем).

Слияние сплющенных форм

В FillFlattenMerge1 мы заполняем формы, используя PdfStamper, Результатом является файл PDF, который хранится в памяти и объединяется с использованием PdfCopy, Хотя этот пример подходит для объединения разных форм, на самом деле это пример того, как этого не делать (как объяснено в видеоуроке).

FillFlattenMerge2 показывает, как объединить идентичные формы, которые правильно заполнены и сведены:

public void manipulatePdf(String src, String dest) throws DocumentException, IOException {
    Document document = new Document();
    PdfCopy copy = new PdfSmartCopy(document, new FileOutputStream(dest));
    document.open();
    ByteArrayOutputStream baos;
    PdfReader reader;
    PdfStamper stamper;
    AcroFields fields;
    StringTokenizer tokenizer;
    BufferedReader br = new BufferedReader(new FileReader(DATA));
    String line = br.readLine();
    while ((line = br.readLine()) != null) {
        // create a PDF in memory
        baos = new ByteArrayOutputStream();
        reader = new PdfReader(SRC);
        stamper = new PdfStamper(reader, baos);
        fields = stamper.getAcroFields();
        tokenizer = new StringTokenizer(line, ";");
        fields.setField("name", tokenizer.nextToken());
        fields.setField("abbr", tokenizer.nextToken());
        fields.setField("capital", tokenizer.nextToken());
        fields.setField("city", tokenizer.nextToken());
        fields.setField("population", tokenizer.nextToken());
        fields.setField("surface", tokenizer.nextToken());
        fields.setField("timezone1", tokenizer.nextToken());
        fields.setField("timezone2", tokenizer.nextToken());
        fields.setField("dst", tokenizer.nextToken());
        stamper.setFormFlattening(true);
        stamper.close();
        reader.close();
        // add the PDF to PdfCopy
        reader = new PdfReader(baos.toByteArray());
        copy.addDocument(reader);
        reader.close();
    }
    br.close();
    document.close();
}

Это три сценария. Ваш вопрос слишком неясен для всех, кроме вас, чтобы решить, какой сценарий лучше всего подходит для ваших нужд. Я предлагаю вам потратить время на изучение, прежде чем писать код. Посмотрите видео, попробуйте примеры, и если у вас все еще есть сомнения, вы сможете опубликовать более умный вопрос.

Другие вопросы по тегам