I need to create a small tool that adds a hyperlink on the first page of a PDF file. I'm using Apache PDFBox to read the pdf files.
Any ideas how to add a hyperlink on a page using this library?
I found this question: how to set hyperlink in content using pdfbox, but this doesn't work.
I just want to add a hyperlink on the first page of a pdf file.
File file = new File(filename);
PDDocument doc = PDDocument.load(file);
PDPage page = doc.getPage(0);
...
I have at least 2 problems with the solution that I found on this question:
The method drawString(String) in the type PDPageContentStream is not applicable for the arguments (PDAnnotationLink)
colourBlue is not initialized
I would prefer to add the hyperlink at the bottom of the page with the URL centered. But for the moment any suggestion will help
First of all, you need to create a PDAnnotationLink like this:
PDAnnotationLink link = new PDAnnotationLink();
The link should have an action:
PDActionURI actionURI = new PDActionURI();
actionUri.setURI("http://www.Google.com");
link.setAction(action);
Finally, you need to define a rectangle at the desired position and finally add the link to the page's annotations.
PDRectangle pdRectangle = new PDRectangle();
pdRectangle.setLowerLeftX(...);
pdRectangle.setLowerLeftY(...);
pdRectangle.setUpperRightX(...);
pdRectangle.setUpperRightY(...);
link.setRectangle(pdRectangle);
page.getAnnotations().add(link);
If you want you can also add an underline for the link by calling the setBorderStyle(...) methid.
Hope this works for you !
If you want to add some text, then you need to create a PDPageContentStream like this:
PDPageContentStream contentStream = new PDPageContentStream(doc, page);
contentStream.beginText();
contentStream.newLineAtOffset(..., ...);
contentStream.showText(...);
contentStream.endText();
contentStream.close();
The newLineAtOffset(..., ...) method is used for positioning the text at the desired location.
P.S. Sorry for the bad indentation but it is pretty hard to write on the mobile. If you need any further help you can even write me a private message in Romanian.
Related
I am using PdfFormXObject pageCopy = sourcePage.CopyAsFormXObject(pdf); to then insert pageCopy into a new PDF page using pdfCanvas.AddXObjectFittedIntoRectangle. The copied page is visible in the new PDF as expected, but it how has it's 'hidden' OCGs visible.
The reason I am doing this is to be able to take a PDF page, scale and crop it and add it to a new PDF where it may be collated with other contents.
Is there a way to remove OCG PDF content prior to create the XObject, or is there a different way of achieving my goal without using the XObject route that allows me to maintain the 'off' status of hidden OCGs
OCG removal functionality is not yet available in iText 7.
There is, however, a workaround that you can try to apply: we can copy all the information about OCGs from your source document to the target document which should create the same OCGs in the target document and preserve default on/off states.
To copy the OCGs, you can copy a page from one document to another one (which is going to copy all the OCGs) and then remove that page.
When the OCG removal functionality becomes available in iText the approach would become cleaner but for now you can use the code similar to the following:
PdfDocument sourceDocument = new PdfDocument(new PdfReader(sourcePdfPath));
PdfDocument targetDocument = new PdfDocument(new PdfWriter(targetPdfPath));
PdfFormXObject pageCopy = sourceDocument.getFirstPage().copyAsFormXObject(targetDocument);
PdfPage page = targetDocument.addNewPage();
PdfCanvas canvas = new PdfCanvas(page);
canvas.addXObject(pageCopy);
// Workaround: copying the page from source document to destination document also copies OCGs
sourceDocument.copyPagesTo(1, 1, targetDocument);
// Workaround: remove the page that we only copied to make sure OCGs are copied
targetDocument.removePage(targetDocument.getNumberOfPages());
sourceDocument.close();
targetDocument.close();
I need to add some text to PDF/A files using the Apache PDFBox library for Java. The problem is that, because it needs to be a valid PDF/A file, all the used fonts must be embedded in it. I know that I can embed a TTF font using PDFBox, but I'd like to avoid having to provide a font file with the application, so I was wondering if there's a way to embed one of the standard fonts available in PDFBox as if it was external.
For example, when I write something using one of the standard fonts, the PDF validator complains about this:
I've used the following code to write the text:
PDFont standardFont = PDType1Font.HELVETICA_BOLD;
PDPage pag = new PDPage();
pag.setResources(new PDResources());
PDPageContentStream contentStream = new PDPageContentStream(pdfFile, pag);
//Begin the Content stream
contentStream.beginText();
//Setting the font to the Content stream
contentStream.setFont(standardFont, 12);
//Setting the position for the line
contentStream.newLineAtOffset(25, 500);
//Adding text in the form of string
contentStream.showText("JUST A SAMPLE STRING");
//Ending the content stream
contentStream.endText();
//Closing the content stream
contentStream.close();
pdfFile.addPage(pag);
pdfFile.save(file);
pdfFile.close();
Is there any option to force the embed of the font when setting it?
Thanks in advance,
There is only one font embedded in PDFBox. You can use it this way:
PDFont font = PDType0Font.load(doc, SomePdfboxClass.class.getResourceAsStream(
"/org/apache/pdfbox/resources/ttf/LiberationSans-Regular.ttf"));
I have a use case that I cannot figure out how to implement.
I'm using headless chrome to export a rich text editor as a pdf and then I need to cut out a part of the created PDF and embed it as a pdf annotation in another parent pdf such that the annotation looks exactly the same as the section I cut out from the created PDF.
I'm able to correctly calculate and cut the precise area I need from the created PDF using instructions provided by:
https://developers.itextpdf.com/examples/stamping-content-existing-pdfs-itext5/cut-and-paste-content-page
PdfTemplate template2 = cb.createTemplate(pageSize.getWidth(), pageSize.getHeight());
template2.rectangle(toMove.getLeft(), toMove.getBottom(), toMove.getWidth(), toMove.getHeight());
template2.clip();
template2.newPath();
template2.addTemplate(page, 0, 0);
cb.addTemplate(template1, 0, 0);
cb.addTemplate(template2, -20, -2);
I would like to add the PDFTemplate via a PdfStamper.
Is this possible? If not now can I achieve this with another method?
In the example you refer to, you obtain cb like this:
PdfContentByte cb = writer.getDirectContent();
When using PdfStamper, you can obtain cb like this:
PdfContentByte cb = stamper.getUnderContent(p);
Or like this:
PdfContentByte cb = stamper.getOverContent(p);
The former method will add the new content under the existing content; the latter method will add the new content on top of the existing content. In these lines p is a page number (from 1 to the total number of pages of the existing document). See How to superimpose pages from existing documents into another document? for an example.
If you want to add new pages to an existing document, use the insertPage() method as explained in How to add blank pages to an existing PDF in java? Once you have added a blank page, you can add a PdfTemplate to it.
My program links a position in a PDF-file to another page in the same file. So you can click on a defined position in the file an you'll be linked to another page.
I use a PDRectangle to define the position. Unfortunately the rectangle is visible in the document. I want to create the link without a visible border.
My code:
PDActionGoTo action = new PDActionGoTo();
action.setDestination(destination);
PDAnnotationLink annotationLink = new PDAnnotationLink();
annotationLink.setAction(action);
PDRectangle position = new PDRectangle();
position.setLowerLeftX(bookmarkLinkPositionEntry.getLowerLeftX());
position.setLowerLeftY(bookmarkLinkPositionEntry.getLowerLeftY());
position.setUpperRightX(bookmarkLinkPositionEntry.getUpperRightX());
position.setUpperRightY(bookmarkLinkPositionEntry.getUpperRightY());
annotationLink.setRectangle(position);
destinationPDF.getPage(0).getAnnotations().add(annotationLink);
I tried to use annotationLink.setHidden(true); and annotationLink.setNoView(true);. The documentation just says "Set the hidden flag." and "Set the noView flag." and I don't know what actually happened there.
How can I change the visibility of my rectangle or remove the border completely?
You'll need to set the border style:
PDBorderStyleDictionary borderULine = new PDBorderStyleDictionary();
borderULine.setStyle(PDBorderStyleDictionary.STYLE_UNDERLINE);
borderULine.setWidth(0);
annotationLink.setBorderStyle(borderULine);
More on this topic in the AddAnnotations.java example in the source code download.
I have a pdf which I'm iterating through using PDFBox as below:
PDDocument doc = PDDocument.load(new ByteArrayInputStream(bytearray));
PDDocumentCatalog catalog = doc.getDocumentCatalog();
for(PDPage page : catalog.getPages()){
...
}
I want to set the default magnification for the pages so that when it is opened through a pdf reader, it opens at 75% zoom by default. Is this possible? I've seen few posts where the zoom is set using PDPageXYZDestination, but I'm not sure whether that is applicable in my case.
Thanks.
Do this, it applies to the first seen page only, i.e. when opening:
PDDocumentCatalog catalog = doc.getDocumentCatalog();
PDPage page = doc.getPage(0); // zero-based; you can also put another number to jump to a specific existing page
PDPageXYZDestination dest = new PDPageXYZDestination();
dest.setPage(page);
dest.setZoom(0.75f);
dest.setLeft((int) page.getCropBox().getLowerLeftX());
dest.setTop((int) page.getCropBox().getUpperRightY());
PDActionGoTo action = new PDActionGoTo();
action.setDestination(dest);
catalog.setActions(null);
catalog.setOpenAction(action);
doc.save(...);