Linking pdfs of Portable Collection using Itext

血红的双手。 提交于 2020-01-03 04:42:11

问题


I have portable collection in that total of two pdf document is there. My requirement is that if I open one pdf document and click the link or any text, it should redirect to another pdf of that portable Collection.

For example: Consider there are two pdfs inside a portable collection namely Programming.pdf and Java.pdf. If I click any particular text or variable inside Programming.pdf, it should redirect to Java.pdf. Is it possible...?.


回答1:


To navigate between documents in a portable collection, you have to employ Embedded Go-To actions. They in particular contain a Target dictionary which actually can be the start of a chain of target dictionaries to navigate between collection members with arbitrary embedding depths. To navigate between sibling documents, you need one target dictionary going up to the parent document containing another target dictionary going down again from that parent to the desired sibling. For details cf. ISO 32000-2 section 12.6.4.4 "Embedded Go-To actions".

In iText 5.x you build such embedded goto actions like this:

PdfTargetDictionary sibbling = new PdfTargetDictionary(true);
sibbling.setEmbeddedFileName(linkId);
PdfTargetDictionary parent = new PdfTargetDictionary(sibbling);
Chunk chunk = new Chunk("Go to " + linkId + ".");
PdfDestination dest = new PdfDestination(PdfDestination.XYZ, -1, -1, 0);
dest.addFirst(new PdfNumber(0));
PdfAction action = PdfAction.gotoEmbedded(null, parent, dest, false);
chunk.setAction(action);
document.add(chunk);

(from EmbeddedLinks helper createPage)

For example the following test creates a portfolio with four documents A, B, C, and D which all contain links to each other:

public void testLinkToSibblingInPortfolio() throws IOException, DocumentException {
    Files.write(new File("portfolio-with-embedded-gotos.pdf").toPath(), createPdf(new String[] {"A", "B", "C", "D"}));
}

public byte[] createPdf(String[] allIds) throws DocumentException, IOException {
    Document document = new Document();
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    PdfWriter writer = PdfWriter.getInstance(document, baos);
    document.open();
    document.add(new Paragraph("This document contains a collection of PDFs."));

    PdfCollection collection = new PdfCollection(PdfCollection.HIDDEN);
    PdfCollectionSchema schema = getCollectionSchema(); 
    collection.setSchema(schema);
    PdfCollectionSort sort = new PdfCollectionSort("TITLE");
    collection.setSort(sort);
    collection.setInitialDocument("A");
    writer.setCollection(collection);

    PdfFileSpecification fs;
    PdfCollectionItem item;
    for (String id : allIds) {
        fs = PdfFileSpecification.fileEmbedded(writer, null,
            String.format("%s.pdf", id),
            createPage(id, allIds));
        fs.addDescription(id, false);

        item = new PdfCollectionItem(schema);
        item.addItem("TITLE", id);
        fs.addCollectionItem(item);
        writer.addFileAttachment(fs);
    }

    document.close();
    return baos.toByteArray();
}

public byte[] createPage(String id, String[] allIds) throws DocumentException, IOException {
    Document document = new Document();
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    PdfWriter.getInstance(document, baos);
    document.open();

    Paragraph p = new Paragraph(id,
        FontFactory.getFont(BaseFont.HELVETICA, BaseFont.WINANSI, BaseFont.NOT_EMBEDDED, 48));
    document.add(p);

    for (String linkId : allIds) {
        if (!id.equals(linkId)) {
            PdfTargetDictionary sibbling = new PdfTargetDictionary(true);
            sibbling.setEmbeddedFileName(linkId);
            PdfTargetDictionary parent = new PdfTargetDictionary(sibbling);
            Chunk chunk = new Chunk("Go to " + linkId + ".");
            PdfDestination dest = new PdfDestination(PdfDestination.XYZ, -1, -1, 0);
            dest.addFirst(new PdfNumber(0));
            PdfAction action = PdfAction.gotoEmbedded(null, parent, dest, false);
            chunk.setAction(action);
            document.add(chunk);
        }
    }

    document.close();
    return baos.toByteArray();
}

private static PdfCollectionSchema getCollectionSchema() {
    PdfCollectionSchema schema = new PdfCollectionSchema();

    PdfCollectionField size = new PdfCollectionField("File size", PdfCollectionField.SIZE);
    size.setOrder(2);
    schema.addField("SIZE", size);

    PdfCollectionField filename = new PdfCollectionField("File name", PdfCollectionField.FILENAME);
    filename.setVisible(false);
    schema.addField("FILE", filename);

    PdfCollectionField title = new PdfCollectionField("Title", PdfCollectionField.TEXT);
    title.setOrder(0);
    schema.addField("TITLE", title);

    return schema;
}

(EmbeddedLinks test testLinkToSibblingInPortfolio and helpers createPdf, createPage, and getCollectionSchema)

This actually borrows a lot from the iText examples KubrickBox, KubrickCollection, and KubrickMovies.


Tested with the current iText 5 development version 5.5.14-SNAPSHOT.



来源:https://stackoverflow.com/questions/53440583/linking-pdfs-of-portable-collection-using-itext

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!