itext7 PDF объединить с закладками - PullRequest
2 голосов
/ 08 июля 2019

Я пытаюсь объединить две PDF-файлы src1 и src2 с закладками, я использовал itext7 для объединения PDF-файлов. PDF-файлы объединяются правильно, но закладки не работают должным образом, закладки из scr1 pdf всегда указывают на scr2 pdf соответственно в объединенном документе.

scr1 bookmark1 ==> указывает на src2 bookmark1

dfDocument pdfDoc = new PdfDocument(new PdfWriter(DEST));
PdfMerger merger = new PdfMerger(pdfDoc);
PdfDocument srcDoc1 = new PdfDocument(new PdfReader(SRC1));
PdfOutline rootOutline = pdfDoc.getOutlines(false);
PdfOutline srcOutline = srcDoc1.getOutlines(false);

PdfDocument srcDoc2 = new PdfDocument(new PdfReader(SRC2));
merger.merge(srcDoc1, 1, srcDoc1.getNumberOfPages());
merger.merge(srcDoc2, 1, srcDoc2.getNumberOfPages());

merger.close();
srcDoc1.close();
srcDoc2.close();
pdfDoc.close();

закладки для одного исходного PDF-файла всегда указывают на исходный 2-й PDF и исходные 2 PDF-закладки работают правильно в объединенном PDF-документе.

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

dfDocument pdfDoc = new PdfDocument(new PdfWriter(DEST));
PdfMerger merger = new PdfMerger(pdfDoc);
PdfDocument srcDoc1 = new PdfDocument(new PdfReader(SRC1));
PdfOutline rootOutline = pdfDoc.getOutlines(false);

PdfOutline srcOutline = srcDoc1.getOutlines(false);
PdfDocument srcDoc2 = new PdfDocument(new PdfReader(SRC2));

merger.merge(srcDoc1, 1, srcDoc1.getNumberOfPages());
merger.merge(srcDoc2, 1, srcDoc2.getNumberOfPages());

for(PdfOutline o : rootOutline.getAllChildren()) {      
    o.addDestination(PdfDestination.makeDestination(new PdfString(o.getTitle().toString())));
}

merger.close();
srcDoc1.close();
srcDoc2.close();
pdfDoc.close();

Ответы [ 2 ]

1 голос
/ 08 июля 2019
Решение

Работает правильно после переименования пункта назначения в уникальный до слияния

PdfDocument srcDoc1 = new PdfDocument(new PdfReader(SRC1));
PdfDocument srcDoc2 = new PdfDocument(new PdfReader(SRC2));
PdfDocument srcDoc3 = new PdfDocument(new PdfReader(SRC3));

renameDest(srcDoc1);
renameDest(srcDoc2);
renameDest(srcDoc3);

merger.merge(srcDoc1, 1, srcDoc1.getNumberOfPages());
merger.merge(srcDoc2, 1, srcDoc2.getNumberOfPages());
merger.merge(srcDoc3, 1, srcDoc3.getNumberOfPages());

merger.close();
srcDoc1.close();
srcDoc2.close();
srcDoc3.close();
pdfDoc.close();

// Метод: renameDest

public static void renameDest(PdfDocument pdf) {

    try {
        String prefix = "cus-" + (index++) + "-";
        PdfNameTree destsTree = pdf.getCatalog().getNameTree(PdfName.Dests);
        PdfNameTree newNameTree = new PdfNameTree(pdf.getCatalog(), PdfName.Dests);
        for (Map.Entry<String, PdfObject> entry : destsTree.getNames().entrySet()) {
            newNameTree.addEntry(prefix + entry.getKey(), entry.getValue());
        }

        for (Map.Entry<String, PdfObject> entry : newNameTree.getNames().entrySet()) {
            destsTree.addEntry(prefix + entry.getKey(), entry.getValue());
            System.out.println(entry.getKey() +"==>>"+ entry.getValue());
        }

        PdfOutline rootOutline = pdf.getOutlines(false);
        updateOutlines(rootOutline, prefix);
    } catch (Exception e) {
        e.printStackTrace();
    }

}

// Метод: updateOutlines

public static void updateOutlines(PdfOutline parentOutline, String prefix) {
    for (PdfOutline outline : parentOutline.getAllChildren()) {
        updateOutlines(outline, prefix);
    }
    if (parentOutline.getDestination() instanceof PdfStringDestination) {
        parentOutline.addDestination(new PdfStringDestination(prefix + ((PdfString) parentOutline.getDestination().getPdfObject()).getValue()));
    }
}
0 голосов
/ 08 июля 2019

Звучит замечательно, как ошибка.

IIRC, есть несколько различных форматов, которые могут использовать закладки ... это может быть просто "страница 7" или "эта область просмотра на этом объекте страницы независимо от того, какой номер страницы это происходит", и несколько вещей между ними .

Ваше решение:

1) Получите копию спецификации PDF (предположительно, Adobe по-прежнему хранит ее, хотя у меня не было необходимости просматривать ее в течение ближайших 10 лет.

2) Посмотрите на разделы "закладки" и "места назначения".

3) Когда вы импортируете любой PDF-файл, просмотрите его закладки и убедитесь, что все места назначения относятся к категории «объект страницы». Возможно, вам придется конвертировать их «вручную», или iText может предоставить это как функцию. Это было долгое время с тех пор, как я работал над iText, понятия не имею, с чем они связались с тех пор.

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

Вам нужно будет использовать базовые манипуляторы PDF на уровне объектов ... PdfString, PdfDictionary, PdfArray и т. Д. ... Я предлагаю iText-RUPS. Он позволяет вам просматривать PDF на уровне базового объекта, чтобы вы могли видеть, что там есть и какой код соответствует. Есть множество таких программ, но это единственная, чье имя я помню по макушке.

...