iText 7 для Java: Полное руководство по созданию и редактированию PDF
iText 7 — это мощная библиотека с открытым исходным кодом (AGPL) для Java, предназначенная для программного создания, манипуляции и рендеринга PDF-документов. Она является преемником популярной библиотеки iText 5 и предлагает полностью переработанную, модульную архитектуру, ориентированную на производительность, гибкость и простоту использования. iText 7 позволяет разработчикам решать широкий спектр задач: от генерации простых счетов и отчетов до создания сложных, юридически значимых документов с цифровыми подписями, формами и метаданными.
Зачем нужна iText 7? В современном мире PDF является универсальным форматом для обмена документами, гарантирующим неизменность отображения на любых устройствах. Ручное создание PDF-файлов трудоемко и неэффективно, особенно при работе с большими объемами данных. iText 7 автоматизирует этот процесс, предоставляя Java-разработчикам полный контроль над каждым аспектом документа: от добавления текста и изображений до создания интерактивных форм и управления правами доступа. Она незаменима в системах документооборота, электронной коммерции, банковском деле и любых других приложениях, где требуется генерация или обработка PDF.
Библиотека поддерживает все последние спецификации PDF, включая PDF 2.0. Она также предоставляет дополнительные модули (add-ons) для работы с HTML-конвертацией (pdfHTML), оптическим распознаванием символов (pdfOCR), созданием SVG (pdfSVG) и обработкой изображений (pdfImage). Важно отметить, что iText 7 распространяется под двойной лицензией: AGPL (требует открытия исходного кода вашего приложения) и коммерческой (для проприетарного использования).
Установка
Для установки iText 7 в ваш проект на Java используется система сборки Maven или Gradle. Ниже приведена точная команда для добавления зависимостей в файл pom.xml (Maven).
<!-- pom.xml -->
<dependencies>
<!-- Основной модуль iText 7 -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext7-core</artifactId>
<version>8.0.4</version> <!-- Проверьте актуальную версию на Maven Central -->
<type>pom</type>
</dependency>
</dependencies>
Для Gradle (build.gradle):
implementation 'com.itextpdf:itext7-core:8.0.4'
Если вам нужны только определенные модули (например, kernel, layout, io), вы можете подключать их по отдельности:
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>kernel</artifactId>
<version>8.0.4</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>layout</artifactId>
<version>8.0.4</version>
</dependency>
Быстрый старт: минимальный рабочий пример
Следующий код создает простой PDF-документ с текстом "Hello, World!" и сохраняет его в файл HelloWorld.pdf.
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.Paragraph;
import java.io.FileNotFoundException;
public class HelloWorld {
public static void main(String[] args) throws FileNotFoundException {
// 1. Создаем PdfWriter, который будет записывать данные в файл
PdfWriter writer = new PdfWriter("HelloWorld.pdf");
// 2. Создаем PdfDocument — объект, представляющий сам PDF-документ
PdfDocument pdf = new PdfDocument(writer);
// 3. Создаем Document — высокоуровневый объект для добавления элементов (текст, таблицы и т.д.)
Document document = new Document(pdf);
// 4. Добавляем абзац с текстом
document.add(new Paragraph("Hello, World!"));
// 5. Закрываем документ (обязательно!)
document.close();
System.out.println("PDF создан успешно!");
}
}
Основные классы и методы
Ниже приведены ключевые классы и методы iText 7, которые вы будете использовать чаще всего.
1. PdfWriter
Сигнатура: PdfWriter(String filename) или PdfWriter(OutputStream outputStream)
Что делает: Создает объект, который управляет записью байтов PDF в файл или поток вывода. Это точка входа для создания нового PDF-документа.
PdfWriter writer = new PdfWriter("output.pdf");
// или в OutputStream:
PdfWriter writer = new PdfWriter(new FileOutputStream("output.pdf"));
2. PdfReader
Сигнатура: PdfReader(String filename) или PdfReader(InputStream inputStream)
Что делает: Создает объект для чтения существующего PDF-документа. Используется для редактирования или анализа PDF.
PdfReader reader = new PdfReader("existing.pdf");
PdfDocument pdfDoc = new PdfDocument(reader, new PdfWriter("modified.pdf"));
3. PdfDocument
Сигнатура: PdfDocument(PdfWriter writer) или PdfDocument(PdfReader reader, PdfWriter writer)
Что делает: Представляет собой модель PDF-документа. Управляет страницами, метаданными и другими глобальными свойствами.
PdfDocument pdf = new PdfDocument(new PdfWriter("doc.pdf"));
// Добавление новой страницы
PdfPage page = pdf.addNewPage();
// Установка метаданных
pdf.getDocumentInfo().setTitle("My Document");
4. Document
Сигнатура: Document(PdfDocument pdfDoc)
Что делает: Высокоуровневый контейнер для добавления элементов (текст, таблицы, изображения) на страницы. Автоматически управляет переносом строк и разбиением на страницы.
Document document = new Document(pdf);
document.add(new Paragraph("Some text"));
document.add(new Table(new float[]{1, 2}));
document.close();
5. Paragraph
Сигнатура: Paragraph(String text) или Paragraph()
Что делает: Представляет собой блок текста. Поддерживает форматирование (шрифт, размер, цвет, выравнивание) и добавление встроенных элементов (например, Text или Image).
Paragraph p = new Paragraph("Hello")
.setFontSize(20)
.setBold()
.setFontColor(ColorConstants.RED);
document.add(p);
6. Table
Сигнатура: Table(float[] columnWidths) или Table(int numColumns)
Что делает: Создает таблицу с заданными ширинами столбцов. Ячейки добавляются с помощью метода addCell().
Table table = new Table(new float[]{1, 3, 2});
table.addCell("Name");
table.addCell("Description");
table.addCell("Price");
table.addCell("Item 1");
table.addCell("Description of item 1");
table.addCell("$10.00");
document.add(table);
7. Cell
Сигнатура: Cell() или Cell(int rowspan, int colspan)
Что делает: Представляет собой ячейку таблицы. Позволяет задавать фон, границы, выравнивание и добавлять вложенные элементы.
Cell cell = new Cell(1, 2) // rowspan=1, colspan=2
.add(new Paragraph("Merged Cell"))
.setBackgroundColor(ColorConstants.LIGHT_GRAY);
table.addCell(cell);
8. Image
Сигнатура: Image(ImageData imageData)
Что делает: Вставляет изображение в документ. ImageData создается фабричным методом ImageDataFactory.create(String path).
ImageData imageData = ImageDataFactory.create("logo.png");
Image img = new Image(imageData)
.setWidth(100)
.setHeight(50);
document.add(img);
9. List
Сигнатура: List()
Что делает: Создает маркированный или нумерованный список. Элементы добавляются методом add(String item) или add(ListItem item).
List list = new List()
.setListSymbol(ListNumberingType.DECIMAL);
list.add("First item");
list.add("Second item");
document.add(list);
10. PdfAcroForm
Сигнатура: PdfAcroForm.getAcroForm(PdfDocument pdfDoc, boolean createIfNotExist)
Что делает: Управляет интерактивными формами (AcroForms) в PDF. Позволяет добавлять текстовые поля, флажки, раскрывающиеся списки и т.д.
PdfAcroForm form = PdfAcroForm.getAcroForm(pdf, true);
PdfTextFormField nameField = PdfTextFormField.createText(pdf, new Rectangle(36, 700, 100, 20), "name", "Enter name");
form.addField(nameField);
Реальный практический пример: Генерация счета-фактуры
В этом примере мы создадим полноценный PDF-документ счета-фактуры, содержащий логотип, заголовок, таблицу с товарами и итоговую сумму.
import com.itextpdf.kernel.colors.ColorConstants;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.borders.Border;
import com.itextpdf.layout.element.*;
import com.itextpdf.layout.properties.UnitValue;
import java.io.FileNotFoundException;
import java.io.IOException;
public class InvoiceGenerator {
public static void main(String[] args) throws IOException {
String dest = "invoice.pdf";
PdfWriter writer = new PdfWriter(dest);
PdfDocument pdf = new PdfDocument(writer);
Document document = new Document(pdf);
// Загрузка шрифта для поддержки кириллицы (если нужно)
PdfFont font = PdfFontFactory.createFont("fonts/arial.ttf", "Cp1251", true);
document.setFont(font);
// 1. Заголовок счета
Paragraph header = new Paragraph("СЧЕТ-ФАКТУРА № 12345")
.setFontSize(24)
.setBold()
.setTextAlignment(TextAlignment.CENTER);
document.add(header);
// 2. Информация о компании и клиенте
document.add(new Paragraph("Продавец: ООО \"Ромашка\""));
document.add(new Paragraph("Покупатель: ИП Иванов И.И."));
document.add(new Paragraph("Дата: 15.10.2024"));
document.add(new Paragraph("Срок оплаты: 30 дней"));
document.add(new Paragraph(" ")); // Пустая строка для отступа
// 3. Таблица с товарами
Table table = new Table(new float[]{1, 4, 2, 2, 2});
table.setWidth(UnitValue.createPercentValue(100));
// Заголовки таблицы
String[] headers = {"№", "Наименование", "Кол-во", "Цена", "Сумма"};
for (String h : headers) {
Cell cell = new Cell().add(new Paragraph(h).setBold().setFontSize(10));
cell.setBackgroundColor(ColorConstants.LIGHT_GRAY);
cell.setTextAlignment(TextAlignment.CENTER);
table.addCell(cell);
}
// Данные товаров
Object[][] items = {
{1, "Товар А", 2, 1000.00, 2000.00},
{2, "Товар Б (услуга)", 1, 5000.00, 5000.00},
{3, "Товар В", 5, 300.00, 1500.00}
};
for (Object[] item : items) {
table.addCell(new Cell().add(new Paragraph(String.valueOf(item[0]))).setTextAlignment(TextAlignment.CENTER));
table.addCell(new Cell().add(new Paragraph((String) item[1])));
table.addCell(new Cell().add(new Paragraph(String.valueOf(item[2]))).setTextAlignment(TextAlignment.CENTER));
table.addCell(new Cell().add(new Paragraph(String.format("%.2f", (Double) item[3]))).setTextAlignment(TextAlignment.RIGHT));
table.addCell(new Cell().add(new Paragraph(String.format("%.2f", (Double) item[4]))).setTextAlignment(TextAlignment.RIGHT));
}
document.add(table);
// 4. Итоговая строка
double total = 0;
for (Object[] item : items) {
total += (Double) item[4];
}
Table totalTable = new Table(new float[]{5, 2});
totalTable.setWidth(UnitValue.createPercentValue(100));
totalTable.addCell(new Cell().add(new Paragraph("Итого:").setBold()).setBorder(Border.NO_BORDER).setTextAlignment(TextAlignment.RIGHT));
totalTable.addCell(new Cell().add(new Paragraph(String.format("%.2f", total)).setBold()).setBorder(Border.NO_BORDER).setTextAlignment(TextAlignment.RIGHT));
document.add(totalTable);
//