Генерация PDF отчётов на Java с iText и Apache PDFBox

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Генерация PDF отчётов на Java: обзор библиотек iText и Apache PDFBox

Создание PDF-документов — одна из частых задач в корпоративных Java-приложениях. Отчёты, счета, накладные, сертификаты — всё это удобно формировать программно. В экосистеме Java есть две основные библиотеки для работы с PDF: iText (промышленный стандарт, но с коммерческой лицензией для новых версий) и Apache PDFBox (полностью бесплатная, открытая). В этой статье разберём обе, покажем примеры кода и поможем выбрать подходящий инструмент для вашего проекта.

1. Apache PDFBox — бесплатная альтернатива с широкими возможностями

Apache PDFBox — это библиотека с открытым исходным кодом (лицензия Apache 2.0). Она позволяет создавать PDF с нуля, редактировать существующие, извлекать текст и метаданные. PDFBox не требует коммерческой лицензии, что делает её идеальным выбором для стартапов и open-source проектов.

Основные возможности:

  • Создание документов с текстом, изображениями, таблицами.
  • Работа со шрифтами (включая кириллицу).
  • Добавление закладок, гиперссылок, водяных знаков.
  • Шифрование и защита паролем.
  • Извлечение текста и изображений из существующих PDF.

Пример: создание простого PDF отчёта с таблицей

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.font.PDType0Font;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import java.io.File;
import java.io.IOException;

public class PdfBoxReport {
    public static void main(String[] args) throws IOException {
        try (PDDocument document = new PDDocument()) {
            PDPage page = new PDPage(PDRectangle.A4);
            document.addPage(page);

            // Загружаем шрифт с поддержкой кириллицы
            PDType0Font font = PDType0Font.load(document, new File("fonts/arial.ttf"));

            try (PDPageContentStream cs = new PDPageContentStream(document, page)) {
                // Заголовок
                cs.beginText();
                cs.setFont(font, 18);
                cs.newLineAtOffset(50, 750);
                cs.showText("Отчёт о продажах за Q1 2025");
                cs.endText();

                // Таблица (простая реализация через линии и текст)
                cs.setFont(font, 12);
                // Рисуем заголовки столбцов
                float margin = 50;
                float yStart = 700;
                float tableWidth = 500;
                float rowHeight = 25;
                String[] headers = {"Товар", "Количество", "Цена, руб."};
                String[][] data = {{"Ноутбук", "10", "85000"}, {"Мышь", "50", "1500"}, {"Клавиатура", "30", "3500"}};

                // Заголовок таблицы
                cs.setLineWidth(1f);
                for (int i = 0; i < headers.length; i++) {
                    cs.addRect(margin + i * (tableWidth / 3), yStart - rowHeight, tableWidth / 3, rowHeight);
                    cs.stroke();
                    cs.beginText();
                    cs.newLineAtOffset(margin + i * (tableWidth / 3) + 5, yStart - rowHeight + 5);
                    cs.showText(headers[i]);
                    cs.endText();
                }

                // Данные
                float yPos = yStart - rowHeight;
                for (String[] row : data) {
                    yPos -= rowHeight;
                    for (int i = 0; i < row.length; i++) {
                        cs.addRect(margin + i * (tableWidth / 3), yPos, tableWidth / 3, rowHeight);
                        cs.stroke();
                        cs.beginText();
                        cs.newLineAtOffset(margin + i * (tableWidth / 3) + 5, yPos + 5);
                        cs.showText(row[i]);
                        cs.endText();
                    }
                }
            }
            document.save("report_pdfbox.pdf");
            System.out.println("PDF создан: report_pdfbox.pdf");
        }
    }
}

Важно: Для корректного отображения кириллицы необходимо использовать шрифт TTF с поддержкой Unicode (например, Arial). PDFBox не встраивает стандартные шрифты автоматически.

2. iText — мощный и гибкий, но с лицензионными ограничениями

iText — это де-факто стандарт для генерации PDF на Java. Версии до iText 5.x распространялись под AGPL (требует открытия исходного кода при коммерческом использовании). Начиная с iText 7, основная лицензия — коммерческая (AGPL остаётся, но с ограничениями). iText предлагает богатый API, поддержку CSS/HTML (через iText pdfHTML), работу с формами, цифровыми подписями и многое другое.

Ключевые фишки iText:

Рекомендаций