Com o utilização da API OpenSource iText, temos a possibilidade de manipular e criar documentos em formato PDF, além de XML e RTF. Devido seu código ser aberto, essa API (biblioteca) tem distriuição sob as licenças LGPL e MPL, proporcionando assim seu uso em diversos sistemas.

Usando essa biblioteca, existe a possibilidade de geração de documentos possuindo textos, imagens, tabelas, e apresenta os mais variados tipos de fontes. Pode ser utilizado em aplicações standalone ou web, com suporte a geração de código de barras (muito útil atualmente).

Será apresentado o uso dessa API (iText) com a criação de um pdf.

Nosso primeiro passo deve ser adicionar o jar do iText ao seu projeto (para os nossos exemplos podemos usar um aplicação Java Project normal).

Nota: O jar pode ser baixado Clicando Aqui

Após fazer o download, devemos adicionar ao "Java Build Path" da aplicação, clique nas propriedades do seu projeto, e adicionar como "Add External Jar" em "Libraries".

Para que seja criado um arquivo em PDF, temos que primeiramente criar um documento, com o uso da classe Document. Este documento pode ser alterado de acordo com as necessidades e/ou requisitos. Abaixo segue uma classe de exemplo:


package devmedia;

import java.io.FileOutputStream;
import java.io.IOException;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.PdfWriter;

public class GeneratorPDF {

    public static void main(String[] args) {
           // criação do documento
          Document document = new Document();
          try {
             
              PdfWriter.getInstance(document, new FileOutputStream("C:\\PDF_DevMedia.pdf"));
              document.open();
             
              // adicionando um parágrafo no documento
              document.add(new Paragraph("Gerando PDF - Java"));
    }
          catch(DocumentException de) {
              System.err.println(de.getMessage());
          }
          catch(IOException ioe) {
              System.err.println(ioe.getMessage());
          }
          document.close();
      }   
    }

Depois de executar a classe acima, observe em C:\\ e note que foi criado um arquivo PDF, conforme conteúdo e nome programado.

A partir de agora, temos uma classe que pode ser usada para geração de vários tipos de arquivos em pdf, com consultas em bancos de dados, como relatórios, entre outros.

Depois dessa primeira experiência com o iText, será apresentado alguns métodos dessa API open source que nos permite uma manipulação maior dos pdf.

O tamanho padrão (default) do pdf gerado pelo iText é o A4. Com o uso do método setPageSize somos capazes de modificar esse atributo. Podemos alterá-lo logo após a abertura desse documento:


document.open();
document.setPageSize(PageSize.A3); // modificado para o tamanho A3;

É possível também adicionar mais páginas para o nosso arquivo pdf, que até agora com possui somente uma página. Essa tarefa é bem simples, basta adicionar um newPage no nosso objeto PDF, observe esse exemplo de código:


document.newPage();
document.add(new Paragraph("Novo parágrafo na nova página"));

Para adicionar um background, acrescente as linhas de código abaixo:


pageSize.setBackgroundColor(new java.awt.Color(0xFF, 0xFF, 0xDE));

Para inserir uma imagem em um documento pdf, temos que utilizar getInstance na imagem que você deseja adicionar, passando como parâmetro o seu caminho (path) e depois adicionar no seu documento com o uso do método add(), como segue abaixo:

Image figura = Image.getInstance("C:\\imagem.jpg");
document.add(figura);

O iText proporciona também a encriptação de documentos. Para tal, precisamos baixar o jar do shared-bouncycastle-reduced-0.9.9.jar, no Clicando Aqui, e também adicionar o buildPath seguindo os mesmos passos do jar do iText. Para isso (encriptografia) é preciso usar o método setEncryption, que tem na sua assinatura o password para abertura do pdf, como mostrado a seguir:


PdfWriter writer = PdfWriter.getInstance(document, 
new FileOutputStream("C:\\Encrypted.pdf"));
writer.setEncryption(PdfWriter.STRENGTH128BITS, "PDFDevmediaJava", 
"devmedia", PdfWriter.AllowCopy | PdfWriter.AllowPrinting);

Após a geração do pdf, ao tentar seu acesso, será apresentado uma caixa para que o usuário digite a senha de acesso do documento. Abaixo segue uma classe de exemplo:


import java.io.FileOutputStream;
import java.io.IOException;

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.PdfWriter;


public class CriptografiaPDF {
   public static void main(String[] args) {
       // criação do objeto documento
      Document document = new Document();
      try {
         
          PdfWriter writer = PdfWriter.getInstance(document, new 
          FileOutputStream("C:\\Encrypted.pdf"));
          writer.setEncryption(PdfWriter.STRENGTH128BITS, 
          "PDFDevmediaJava", "devmedia", PdfWriter.AllowCopy 
          | PdfWriter.AllowPrinting);
          document.open();
          document.add(new Paragraph("Exemplo Criptografia"));
      }
      catch(DocumentException de) {
          System.err.println(de.getMessage());
      }
      catch(IOException ioe) {
          System.err.println(ioe.getMessage());
      }
      document.close();
  }   

}

É importante saber que a senha é case sensitive.

Existe também a possibilidade de inserir os metadados ao seu documento, com a utilização dos métodos como addSubject e addAuthor:


document.addSubject("Gerando PDF em Java"); document.addKeywords("www.devmedia.com.br");
document.addCreator("iText");
document.addAuthor("Davi Gomes da Costa");

Todas essas informações podem ser notadas nas propriedades do arquivo.

Abaixo mais uma classe de exemplo com o uso de metadados:


import java.io.FileOutputStream;
import java.io.IOException;

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.PdfWriter;


public class GeneratorPDFMetadados {
   
   public static void main(String[] args) {
       // criação do objeto documento
      Document document = new Document();
      try {
         
          PdfWriter.getInstance(document, 
          new FileOutputStream("C:\\PDF_DevMedia.pdf"));
          document.open();
         
          // adicionando um parágrafo ao documento
          document.add(new Paragraph("Gerando PDF em Java - metadados"));
          document.addSubject("Gerando PDF em Java");
          document.addKeywords("www.devmedia.com.br");
          document.addCreator("iText");
          document.addAuthor("Davi Gomes da Costa");
}
      catch(DocumentException de) {
          System.err.println(de.getMessage());
      }
      catch(IOException ioe) {
          System.err.println(ioe.getMessage());
      }
      document.close();
  }   

}

Há outras possibilidades de manipulação mais avançadas que podem ser encontradas em PdfStamper e PdfCopy, que proporciona, respectivamente, a leitura e/ou alteração de um pdf já existente e a inserção do conteúdo de um documento em um segundo pdf.

Abaixo temos um exemplo de classe que copia o conteúdo de um pdf em um segundo pdf:


package devmedia;

import java.io.FileOutputStream;

import com.itextpdf.text.Document;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfImportedPage;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfWriter;


public class ParsingPDF {
  
public static void main(String[] args) {
    try {
      // cria o reader para o pdf já criado
      PdfReader reader = new PdfReader("C:\\PDF_DevMedia.pdf");
      // n recebe o numero total de páginas
      int n = reader.getNumberOfPages();
      // tamanho da primeira página
      Rectangle psize = reader.getPageSize(1);
      float width = psize.getHeight();
      float height = psize.getWidth();

      // crie o segundo pdf
      Document document = 
      new Document(new Rectangle(width, height));
      PdfWriter writer = PdfWriter.getInstance(document, 
      new FileOutputStream("C:\\SegundoPDF.pdf"));
      document.open();
      // adiciona conteúdo ao segundo pdf
      PdfContentByte cb = writer.getDirectContent();
      int i = 0;
      int p = 0;
      while (i < n) {
         document.newPage();
         p++;
         i++;
         PdfImportedPage page1 = writer.getImportedPage(reader, i);
         cb.addTemplate(page1, .5f, 0, 0, .5f, 60, 120);
         if (i < n) {
            i++;
            PdfImportedPage page2 = writer.getImportedPage(reader, i);
            cb.addTemplate(page2, .5f, 0, 0, .5f, width / 2 + 60, 120);
         }
         BaseFont bf = BaseFont
         .createFont(BaseFont.HELVETICA, 
         BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
         cb.beginText();
         cb.setFontAndSize(bf, 14);
         cb.showTextAligned(PdfContentByte
         .ALIGN_CENTER, "page " + p + " of " + ((n / 2) + (n % 2 >
         0? 1 : 0)), width / 2, 40, 0);
         cb.endText();
      }
      document.close();
    }
    catch (Exception de) {
      de.printStackTrace();
    }
}
}
Observação: para que essa classe execute sem erros é necessário que o arquivo especificado no caminho C:\\PDF_DevMedia.pdf exista, para isso basta que executemos nossa primeira classe de exemplo do artigo. Para maiores informações veja as referências.

Referências: