July 13, 2022

Generating PDF in Java Using PDFBox Tutorial

We have already seen examples of generating PDF in Java using iText and generating PDF in Java using OpenPDF. In this post we’ll learn about another option for generating PDF in Java using Apache PDFBox.

Apache PDFBox library

The Apache PDFBox library (https://pdfbox.apache.org/) is an open source Java tool for working with PDF documents. This project allows creation of new PDF documents, manipulation of existing documents and the ability to extract content from documents.

Maven Dependency for PDFBox

<dependency>
  <groupId>org.apache.pdfbox</groupId>
  <artifactId>pdfbox</artifactId>
  <version>2.0.13</version>
</dependency>

Examples of PDF generation using PDFBox and Java given in this post.

HelloWorld PDF using Java and PDFBox

We’ll start with creating a simple HelloWorld PDF which also shows font and text color settings for the content. For creating a PDF using PDFBox and adding content to it you need to do the following steps.

  1. Create a new PDF document using PDDocument class. Instantiating this class you can create an empty PDF document.
  2. Add page to that empty PDF document using PDPage class. This adds a blank page to the PDF document.
  3. Write to that page using PDPageContentStream class.
  4. You need to call beginText() method of the PDPageContentStream class before starting text operations and endText() method to end text operations.
  5. For setting the starting position for the line use newLineAtOffset() method. Original position on a page is at the bottom left corner, you need to bring it to the position from where you want the text to start.
import java.awt.Color;
import java.io.IOException;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.font.PDType1Font;

public class HelloWorldPDF {
  public static final String CREATED_PDF = "F://knpcode//result//PDFBox//HelloWorld.pdf";
  public static void main(String[] args) {
    try {
      PDDocument pdfDoc = new PDDocument();
      PDPage firstPage = new PDPage();
      // add page to the PDF document
      pdfDoc.addPage(firstPage);
      // For writing to a page content stream
      try(PDPageContentStream cs = new PDPageContentStream(pdfDoc, firstPage)){
        cs.beginText();
        // setting font family and font size
        cs.setFont(PDType1Font.COURIER, 15);
        // color for the text
        cs.setNonStrokingColor(Color.RED);
        // starting position
        cs.newLineAtOffset(20, 750);
        cs.showText("Hello World PDF created using PDFBox");
        // go to next line
        cs.newLine();
        cs.endText();
      }
      // save PDF document
      pdfDoc.save(CREATED_PDF);
      pdfDoc.close();
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }
}
Hello World PDFBox Java

Adding Multiple lines and multi-line text to PDF using PDFBox

If you have to add multiple lines to PDF and there is a text that spans multiple lines then the extra methods that you need to use are-

  1. Use newLine() method of the PDPageContentStream class to move to the start of the next line of text. This requires the leading to have been set which can be done using setLeading() method.
  2. For text spanning multiple lines there is no support in PDFBox so you need to do that calculation using the allowed width for the page and using the font size and width to calculate the space taken by each word in the line.
import java.awt.Color;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.font.PDFont;
import org.apache.pdfbox.pdmodel.font.PDType1Font;

public class CreatePDF {
  public static final String CREATED_PDF = "F://knpcode//result//PDFBox//Content.pdf";
  public static void main(String[] args) {
    try {
      PDDocument pdfDoc = new PDDocument();
      PDPage firstPage = new PDPage();
      // add page to the PDF document
      pdfDoc.addPage(firstPage);
      // For writing to a page content stream
      try(PDPageContentStream cs = new PDPageContentStream(pdfDoc, firstPage)){
        cs.beginText();
        cs.setFont(PDType1Font.COURIER, 15);
        cs.newLineAtOffset(20, 750);
        cs.setLeading(12);
        cs.showText("Hello World PDF created using PDFBox");
        cs.newLine();
        String text = "This text spans multiple lines and it is added to the PDF dcoument generated using PDFBox";
        showMultiLineText(text, 20, 762, 580, firstPage, cs, PDType1Font.COURIER, 15);
        cs.setFont(PDType1Font.TIMES_BOLD, 15);
        cs.setNonStrokingColor(Color.RED);
        cs.showText("While adding this line font and color settings are changed.");
        cs.newLine();
        cs.endText();
      }
      pdfDoc.save(CREATED_PDF);
      pdfDoc.close();
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }
	
  private static void showMultiLineText(String text, int x, int y, int allowedWidth, PDPage page, PDPageContentStream contentStream, PDFont font, int fontSize) throws IOException {
    List<String> lines = new ArrayList<String>();
    String line = "";
    // split the text on spaces
    String[] words = text.split(" ");
    for(String word : words) {
      if(!line.isEmpty()) {
        line += " ";
      }
      // check if adding the word to the line surpasses the width of the page
      int size = (int) (fontSize * font.getStringWidth(line + word) / 1000);
      if(size > allowedWidth) {
        // if line + word surpasses the width of the page, add the line without the current word
        lines.add(line);
        // start new line with the current word
        line = word;
      } else {
        // if line + word fits the page width, add the current word to the line
        line += word;
      }
    }
    lines.add(line);
    for(String ln : lines) {
      System.out.println("Line- " + ln);    
      contentStream.showText(ln);
      contentStream.newLine();
    }
  }
}
MultiLine Text PDFBox

Adding text to an existing PDF using PDFBox

If you want to add a new page to an existing PDF document then you can load existing PDF using load() method of the PDDocument class.

import java.io.File;
import java.io.IOException;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.font.PDType1Font;

public class CreatePDF {
  public static final String CREATED_PDF = "F://knpcode//result//PDFBox//Content.pdf";
  public static void main(String[] args) {
    try {
      // Load existing PDF
      PDDocument pdfDoc = PDDocument.load(new File(CREATED_PDF));
      PDPage page = new PDPage();
      // add page to the PDF document
      pdfDoc.addPage(page);
      // For writing to a page content stream
      try(PDPageContentStream cs = new PDPageContentStream(pdfDoc, page)){
        cs.beginText();
        cs.setFont(PDType1Font.TIMES_ROMAN, 12);
        cs.newLineAtOffset(20, 750);
        cs.setLeading(12);
        cs.showText("This is a new page added to an existing PDF document");
        cs.newLine();
        cs.endText();
      }
      pdfDoc.save(CREATED_PDF);
      pdfDoc.close();
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }
}

Converting text file to PDF using PDFBox

In the Java example there is a text file (Test.txt) which is converted to a PDF using PDFBox. In this example we’ll also cover the scenario where apart from text that may span multiple lines there is content that may span multiple pages in the PDF. In PDFBox each new page has to be created and added to the document before content can be written to that page.

For content in multiple pages in PDFBox you need to keep track of the height of the content in the page and when that height exceeds the allowed height add a new page. Allowed height may vary based on the type of the document, in this example A4 page size is considered.

Current height is calculated by adding line height to current height for each line written to the PDF document.

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.font.PDFont;
import org.apache.pdfbox.pdmodel.font.PDType1Font;

public class CreatePDF {
  // Text file that has to be converted
  public static final String SOURCE_FILE = "F://knpcode//result//Test.txt";
  public static final String CREATED_PDF = "F://knpcode//result//PDFBox//Content.pdf";
  static double currentHeight = 0;
  static PDPageContentStream cs = null;
  public static void main(String[] args) {
    try {
      PDDocument pdfDoc = new PDDocument();
      // for text file
      BufferedReader br = new BufferedReader(new FileReader(SOURCE_FILE));
      PDPage page = new PDPage();
      // add page to the PDF document
      pdfDoc.addPage(page);
      String line;
      cs = new PDPageContentStream(pdfDoc, page);
      cs.beginText();
      cs.setFont(PDType1Font.TIMES_ROMAN, 12);
      cs.newLineAtOffset(20, 750);
      cs.setLeading(12);
      // Read text file line by line
      while ((line = br.readLine()) != null) {
        System.out.println("Line-- " + line);
        showMultiLineText(pdfDoc, line, 20, 750, 580, 820, page, PDType1Font.TIMES_ROMAN, 15);				
      }				
      if(cs != null) {
        cs.endText();
        cs.close();
      }
      pdfDoc.save(CREATED_PDF);
      br.close();
      pdfDoc.close();
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }
	
  /**
   * 
   * @param pdfDoc
   * @param text
   * @param x
   * @param y
   * @param allowedWidth - allowed width for the line before content goes to next line
   * @param allowedHeight - Allowed height for the page before another page is added
   * @param page
   * @param font
   * @param fontSize
   * @throws IOException
   */
  private static void showMultiLineText(PDDocument pdfDoc, String text, int x, int y, int allowedWidth, double allowedHeight, PDPage page, PDFont font, int fontSize) throws IOException {
    List<String> lines = new ArrayList<String>();
    String line = "";
    // split the text on spaces
    String[] words = text.split(" ");
    for(String word : words) {
      if(!line.isEmpty()) {
        line += " ";
      }
      // check if adding the word to the line surpasses the width of the page
      int size = (int) (fontSize * font.getStringWidth(line + word) / 1000);
      if(size > allowedWidth) {
        // if line + word surpasses the width of the page, add the line without the current word
        lines.add(line);
        // start new line with the current word
        line = word;
      } else {
        // if line + word fits the page width, add the current word to the line
        line += word;
      }
    }
    lines.add(line);

    for(String ln : lines) {
      System.out.println("Line- " + ln); 
      // for each line add line height to current height 
      // line height = 1.2 * fontSize is taken here 
      currentHeight = currentHeight + 1.2 * fontSize;
      System.out.println("currentHeight " + currentHeight);

      if(currentHeight >= allowedHeight) {
        System.out.println("adding new page " + currentHeight);
        // When current height is more than allowed height for the page
        // create a new page
        page = new PDPage();
        // add page to the PDF document
        pdfDoc.addPage(page);
        // reset currentHeight
        currentHeight = 0;
        cs.endText();
        cs.close();
        cs = new PDPageContentStream(pdfDoc, page);
        cs.beginText();
        cs.setFont(PDType1Font.TIMES_ROMAN, 12);
        cs.newLineAtOffset(20, 750);
        cs.setLeading(12);
      }
      cs.showText(ln);
      cs.newLine();  
    }
  }
}

Adding image to a PDF documents using PDFBox

To add an image to PDF document, PDImageXObject class in PDFBox library is used.

import java.io.IOException;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.font.PDType1Font;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;

public class PDFImage {
  public static final String CREATED_PDF = "F://knpcode//result//PDFBox//Image.pdf";
  public static void main(String[] args) {		
    PDDocument pdfDoc;
    try {
      pdfDoc = new PDDocument();	
      PDPage page = new PDPage();
      pdfDoc.addPage(page);
      // Create image object using the image location
      PDImageXObject image = PDImageXObject.createFromFile("images//PDFBox image.png", pdfDoc);
      try(PDPageContentStream cs = new PDPageContentStream(pdfDoc, page)){
        cs.beginText();
        // setting font family and font size
        cs.setFont(PDType1Font.HELVETICA_BOLD, 14);
        // starting position in the page
        cs.newLineAtOffset(20, 700);
        cs.setLeading(12);
        cs.showText("In this page an image is added using PDFBox");
        cs.newLine();
        cs.endText();
        cs.drawImage(image, 20, 550);
      }
      pdfDoc.save(CREATED_PDF);
      pdfDoc.close();
        
    }catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }		
  }
}
Image PDFBox Java

That's all for the topic Generating PDF in Java Using PDFBox Tutorial. If something is missing or you have something to share about the topic please write a comment.


You may also like

No comments:

Post a Comment