Adding Top level Bookmark to the exsting PDF using PDFBOX - java

I would like to add a top level bookmark to an existing pdf file using PDFBOX in JAVA.
Not sure why the following code was not working, can anyone help me out? Thanks.
Below is how the Document.pdf looks like in the bookmark section.
Top
---Node-1
-------Node-11
-------Node-12
....
---Node-2
-------Node-21
....
Java code (Part within the program) :
PDDocument document = PDDocument.load(new File("C:/Users/Desktop/document.pdf"))
PDDocumentOutline documentOutline = new PDDocumentOutline();
document.getDocumentCatalog().setDocumentOutline(documentOutline);
PDOutlineItem pagesOutline = new PDOutlineItem();
pagesOutline.setTitle("All Pages");
documentOutline.addFirst(pagesOutline);
pagesOutline.openNode();
documentOutline.openNode();
document.getDocumentCatalog().setPageMode(PageMode.USE_OUTLINES);
document.save("C:/Users/Desktop/document.pdf");
document.close()

Here's my attempt at this, I'm keeping my filename if asked questions later.
What I did is to wrap the old outline into a new item. It is not possible to add the existing items one by one, because only "orphans" can be added.
PDDocument document = PDDocument.load(new File("000009.pdf"));
PDDocumentOutline oldDocumentOutline = document.getDocumentCatalog().getDocumentOutline();
PDDocumentOutline documentOutline = new PDDocumentOutline();
document.getDocumentCatalog().setDocumentOutline(documentOutline);
PDOutlineItem pagesOutline = new PDOutlineItem();
//pagesOutline.setTitle("All Pages");
//documentOutline.addFirst(pagesOutline);
PDOutlineItem oldOutlineItemWrapped = new PDOutlineItem(oldDocumentOutline.getCOSObject());
oldOutlineItemWrapped.setTitle("All Pages");
documentOutline.addFirst(oldOutlineItemWrapped);
//pagesOutline.openNode();
oldOutlineItemWrapped.openNode();
documentOutline.openNode();
document.getDocumentCatalog().setPageMode(PageMode.USE_OUTLINES);
document.save("000009-modified.pdf");
document.close();

Related

The issue of Link API in iText7

When I generate a pdf document with Link API, there have some strange things. A rectangle always outside the link text. It looks like the cell rectangle, but I didn't set any cell in the document.
My code is like this:
try (PdfDocument pdfDocument = new PdfDocument(new PdfWriter(file));
Document document = new Document(pdfDocument);) {
PdfAction pdfAction = PdfAction.createURI("https://kb.itextpdf.com/home");
Link link = new Link("https://kb.itextpdf.com/home", pdfAction);
Paragraph paragraph = new Paragraph();
paragraph.add(link);
document.add(paragraph);
} catch (Exception e) {
System.out.println(e);
}
I resolved it like this:
PdfLinkAnnotation linkAnnotation = link.getLinkAnnotation();
linkAnnotation.setBorder(new PdfAnnotationBorder(0, 0, 0));

How do you add multiple images to a PDF with itext7 Java?

First google result takes me to Add multiple images into a single pdf file with iText using java which was posted 5 years ago. I am not sure which version they are using, because the Image object doesn't even have the getInstance method for me. Needless to say I am not getting much help from that link.
Anyways I am trying to create a javaFX application that loops multiple JPG images to create a single PDF document. Below is my code, which successfully creates a PDF from 2 images, but I am having trouble making the second image display on the second page.
In the link I posted above the simple solution I saw was to do document.newPage() then do document.add(img), but my document object doesn't have that method? I am not sure what to do.
PdfWriter writer = new PdfWriter("D:/sample1.pdf");
// Creating a PdfDocument
PdfDocument pdfDoc = new PdfDocument(writer);
// Adding a new page
// I can add multiple pages here, but when I add multiple images they do not
// automatically flow over to the next page.
pdfDoc.addNewPage();
pdfDoc.addNewPage();
// Creating a Document
Document document = new Document(pdfDoc);
String imageFile = "C:/Users/***/Downloads/MAT204/1.3-1.4 HW/test.jpg";
ImageData data = ImageDataFactory.create(imageFile);
Image img = new Image(data);
img.setAutoScale(true);
img.setRotationAngle(-Math.toRadians(90));
// I can add multiple images, but they overlaps each other and only
// appears on the first page.
// Is there a way for me to change the current page to write on?
document.add(img);
document.add(img);
// Closing the document
document.close();
System.out.println("PDF Created");
Anyways, I just want to figure out how to manually add another image before I write a loop to automate the process.
After doing more research I found the answer here.
https://kb.itextpdf.com/home/it7kb/examples/multiple-images
protected void manipulatePdf(String dest) throws Exception {
Image image = new Image(ImageDataFactory.create(IMAGES[0]));
PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
Document doc = new Document(pdfDoc, new PageSize(image.getImageWidth(), image.getImageHeight()));
for (int i = 0; i < IMAGES.length; i++) {
image = new Image(ImageDataFactory.create(IMAGES[i]));
pdfDoc.addNewPage(new PageSize(image.getImageWidth(), image.getImageHeight()));
image.setFixedPosition(i + 1, 0, 0);
doc.add(image);
}
doc.close();
}

What is the correct way to deep clone PDPage?

I am working with PDFBOX v2, I'm trying to clone the first PDPage of a PDDocument for keep it as template for new PDPages. That first page, has some acroform fields that I need fill.
I tried some methods but anyone makes I want to achieve.
1) Copy the first page content and add it to the document when I need a new page. That copy the page but the acroform field are linked with other pages fields, and if I modify field value from the first page, that shows in the other pages.
//Save in variable first page content
COSDictionary pageContent = (COSDictionary)doc.getPage(0).getCOSObject();
...
//when i need insert new page
doc.addPage(new PDPage(pageContent));
2) Clone the first page content and then add to the document like the first method. That copy the page but no field is copied :/
PDFCloneUtility cloner = new PDFCloneUtility(doc);
COSDictionary pageContent = (COSDictionary)cloner.cloneForNewDocument(doc.getPage(0).getCOSObject());
...
//when i need insert new page
doc.addPage(new PDPage(pageContent));
Then, what is the correct way to make a deep copy of a PDPage getting acroform fields independent from the first page?
Thanks!
I got the solution!
1) Start with an empty pdf template, only has 1 page. Open template document, fill common data and save as byte[] in memory.
PDDocument templatedoc = PDDocument.load(new File(path));
PDDocumentCatalog catalog = templatedoc.getDocumentCatalog();
PDAcroFrom acroForm = catalog.getAcroForm());
... fill acroForm common data of all pages ...
ByteArrayOutputStream basicTemplate = new ByteArrayOutputStream();
templatedoc.save(basicTemplate);
byte[] filledBasicTemplate = basicTemplate.toByteArray();
2) Generate new document for each needed page.
List<PDDocument> documents = new ArrayList<PDDocument>();
PDDocument activeDoc;
for(int i = 0; i < 5; i++) {
activeDoc = PDDocument.load(filledBasicTemplate);
documents.add(activeDoc);
... fill acroform or you need in each page ...
}
3) Import all new document first pages into final document and save final document.
PDDocument finalDoc = new PDDocument();
for(PDDocument currentDoc : documents) {
... fill common things like page numbers ...
finalDoc.importPage(currentDoc.getPage(0));
}
finalDoc.save(new File(path));
... close all documents after save the final document ...
It maybe not be the most optimized code, but it works.

Table of Contents in Landscape mode with Clickable local links

I'm trying to create table of contents page for my PDF in Landscape mode and the links are not working as they do in Portrait mode.
Here's the sample code:
Document doc = new Document(PageSize.A4.rotate());
PffWriter.getInstance(doc, new FileOutputStream("test.pdf"));
doc.open();
// Create a chunk and add it to the document.
Chunk chunk = new Chunk("Click this link to goto second page.");
chunk.setUnderline(0.2f, -2f);
chunk.setLocalGoto("test");
chunk.setLocalDestination("test1");
doc.add(chunk);
// Skip rest of current page and begin a new page.
doc.add(Chunk.NEXTPAGE);
// Create a chunk and add it to the document.
chunk = new Chunk("Click this link to goto first page.");
chunk.setUnderline(0.2f, -2f);
chunk.setLocalGoto("test1");
chunk.setLocalDestination("test");
doc.add(chunk);
doc.close();
Instead of:
Document doc = new Document(PageSize.A4.rotate());
if i do:
Document doc = new Document(PageSize.A4);
it works as expected and the links work very well. But it fails in the landscape mode.

How to add an image in the last page of pdf using iText?

How do i add an image on the last page of existing PDF document. Please help me.
The following example adds an image to the second page of an existing pdf using Itext 5.
String src = "c:/in.pdf;
String dest = "c:/out.pdf";
String IMG = "C:/image.jpg";
try {
PdfReader reader = new PdfReader(src);
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
com.itextpdf.text.Image image = com.itextpdf.text.Image.getInstance(IMG);
image.setAbsolutePosition(36, 400);
PdfContentByte over = stamper.getOverContent(2);
over.addImage(image);
stamper.close();
reader.close();
} catch (Exception e) {
e.printStackTrace();
}
You can read the text from the PDF using the same ITEXT library.Try this
PdfReader reader = new PdfReader(INPUTFILE);
int n = reader.getNumberOfPages();
PdfTextExtractor parser =new PdfTextExtractor(new PdfReader("C:/Text.pdf"));
parser.getTextFromPage(3); // Extracting the content from a particular page.
After you have add your data ,You can load images either from file or from a URL, like this:
Image image1 = Image.getInstance("watermark.png");
document.add(image1);
String imageUrl = "http://applause-voice.com/wp-content/uploads/2011/04/1hello.jpg";
Image image2 = Image.getInstance(new URL(imageUrl));
document.add(image2);
If you will add this code at the end of your Java Program , then the image will automatically comes at the end of your page.
The best solution for me was to create a new in-memory PDF document with the image I want to add, then copy this page to the original document.
// Create a separate doc for image
var pdfDocWithImageOutStream = new ByteArrayOutputStream();
var pdfDocWithImage = new PdfDocument(new PdfWriter(pdfDocWithImageOutStream).setSmartMode(true));
var docWithImage = new Document(pdfDocWithImage, destinationPdf.getDefaultPageSize());
// Add image to the doc
docWithImage.add(image);
// Close the doc to save data
docWithImage.close();
pdfDocWithImage.close();
// Open the same doc for reading
pdfDocWithImage = new PdfDocument(new PdfReader(new ByteArrayInputStream(pdfDocWithImageOutStream.toByteArray())));
docWithImage = new Document(pdfDocWithImage, destinationPdf.getDefaultPageSize());
// Copy page to original (destinationPdf)
pdfDocWithImage.copyPagesTo(1, pdfDocWithImage.getNumberOfPages(), destinationPdf);
docWithImage.close();
pdfDocWithImage.close();

Categories