Создание PDF-файлов на Java

Создание PDF-файлов в Java

1. Вступление

В этой быстрой статье мы сосредоточимся на создании PDF-документа с нуля на основе популярных библиотек iText и PdfBox.

2. Maven Зависимости

Давайте посмотрим на зависимости Maven, которые необходимо включить в наш проект:


    com.itextpdf
    itextpdf
    5.5.10


    org.apache.pdfbox
    pdfbox
    2.0.4

Последнюю версию библиотек можно найти здесь:iText иPdfBox.

Необходимо добавить еще одну зависимость, если наш файл необходимо зашифровать. Пакет Bounty Castle Provider содержит реализации криптографических алгоритмов и требуется обеими библиотеками:


    org.bouncycastle
    bcprov-jdk15on
    1.56

Последнюю версию библиотеки можно найти здесь:The Bounty Castle Provider.

3. обзор

И iText, и PdfBox являются библиотеками Java, используемыми для создания / манипулирования файлами PDF. Хотя окончательный вывод библиотек один и тот же, они работают немного по-другому. Давайте посмотрим на них.

4. Создать PDF в IText

4.1. Вставить текст в PDF

Давайте посмотрим, как новый файл с текстом «Hello World» вставляется в файл pdf

Document document = new Document();
PdfWriter.getInstance(document, new FileOutputStream("iTextHelloWorld.pdf"));

document.open();
Font font = FontFactory.getFont(FontFactory.COURIER, 16, BaseColor.BLACK);
Chunk chunk = new Chunk("Hello World", font);

document.add(chunk);
document.close();

Создание PDF-файла с использованием библиотеки iText основано на манипулировании объектами, реализующими интерфейсElements вDocument (в версии 5.5.10 таких реализаций 45).

Наименьший элемент, который можно добавить в документ и использовать, называетсяChunk, который по сути представляет собой строку с примененным шрифтом.

Кроме того,Chunk's можно комбинировать с другими элементами, такими какParagraphs,Section и т. Д. в результате получаются красивые документы.

4.2. Вставка изображения

Библиотека iText предоставляет простой способ добавить изображение в документ. Нам просто нужно создать экземплярImage и добавить его вDocument.

Path path = Paths.get(ClassLoader.getSystemResource("Java_logo.png").toURI());

Document document = new Document();
PdfWriter.getInstance(document, new FileOutputStream("iTextImageExample.pdf"));
document.open();
Image img = Image.getInstance(path.toAbsolutePath().toString());
document.add(img);

document.close();

4.3. Вставка таблицы

Мы можем столкнуться с проблемой, когда хотим добавить таблицу в наш pdf. К счастью, iText предоставляет такие функциональные возможности.

Сначала нам нужно создать объектPdfTable и в конструкторе предоставить несколько столбцов для нашей таблицы. Теперь мы можем просто добавить новую ячейку, позвонив

Теперь мы можем просто добавить новую ячейку, вызвав методaddCell для вновь созданного объекта таблицы. iText будет создавать строки таблицы до тех пор, пока все необходимые ячейки определены, это означает, что, как только вы создадите таблицу с 3 столбцами и добавите в нее 8 ячеек, будут отображаться только 2 строки с 3 ячейками в каждой.

Давайте посмотрим на пример:

Document document = new Document();
PdfWriter.getInstance(document, new FileOutputStream("iTextTable.pdf"));

document.open();

PdfPTable table = new PdfPTable(3);
addTableHeader(table);
addRows(table);
addCustomRows(table);

document.add(table);
document.close();

Мы создаем новую таблицу с 3 столбцами и 3 строками. Первую строку мы будем рассматривать как заголовок таблицы с измененным цветом фона и шириной границы:

private void addTableHeader(PdfPTable table) {
    Stream.of("column header 1", "column header 2", "column header 3")
      .forEach(columnTitle -> {
        PdfPCell header = new PdfPCell();
        header.setBackgroundColor(BaseColor.LIGHT_GRAY);
        header.setBorderWidth(2);
        header.setPhrase(new Phrase(columnTitle));
        table.addCell(header);
    });
}

Второй ряд будет состоять из трех ячеек только с текстом, без дополнительного форматирования.

private void addRows(PdfPTable table) {
    table.addCell("row 1, col 1");
    table.addCell("row 1, col 2");
    table.addCell("row 1, col 3");
}

Мы можем включать не только текст в ячейки, но и изображения. Кроме того, каждая ячейка может быть отформатирована индивидуально, в примере, представленном ниже, мы применяем корректировки горизонтального и вертикального выравнивания:

private void addCustomRows(PdfPTable table)
  throws URISyntaxException, BadElementException, IOException {
    Path path = Paths.get(ClassLoader.getSystemResource("Java_logo.png").toURI());
    Image img = Image.getInstance(path.toAbsolutePath().toString());
    img.scalePercent(10);

    PdfPCell imageCell = new PdfPCell(img);
    table.addCell(imageCell);

    PdfPCell horizontalAlignCell = new PdfPCell(new Phrase("row 2, col 2"));
    horizontalAlignCell.setHorizontalAlignment(Element.ALIGN_CENTER);
    table.addCell(horizontalAlignCell);

    PdfPCell verticalAlignCell = new PdfPCell(new Phrase("row 2, col 3"));
    verticalAlignCell.setVerticalAlignment(Element.ALIGN_BOTTOM);
    table.addCell(verticalAlignCell);
}

4.4. Шифрование файлов

Чтобы применить разрешение с использованием библиотеки iText, нам нужно уже создать документ в формате PDF. В нашем примере мы будем использовать наш файлiTextHelloWorld.pdf, созданный ранее.

После того, как мы загрузим файл с помощьюPdfReader, нам нужно создатьPdfStamper, который используется для применения дополнительного содержимого к файлу, такого как метаданные, шифрование и т. Д .:

PdfReader pdfReader = new PdfReader("HelloWorld.pdf");
PdfStamper pdfStamper
  = new PdfStamper(pdfReader, new FileOutputStream("encryptedPdf.pdf"));

pdfStamper.setEncryption(
  "userpass".getBytes(),
  ".getBytes(),
  0,
  PdfWriter.ENCRYPTION_AES_256
);

pdfStamper.close();

В нашем примере мы зашифровали файл двумя паролями. Пароль пользователя («userpass»), где пользователь имеет право только на чтение, без возможности распечатать его, и пароль владельца («ownerpass»), который используется в качестве главного ключа, позволяющего человеку иметь полный доступ к pdf.

Если мы хотим разрешить пользователю печатать pdf, вместо 0 (третий параметрsetEncryption) мы можем передать:

PdfWriter.ALLOW_PRINTING

Конечно, мы можем смешивать различные разрешения, такие как:

PdfWriter.ALLOW_PRINTING | PdfWriter.ALLOW_COPY

Имейте в виду, что используя iText для установки прав доступа, мы также создаем временный PDF-файл, который следует удалить, а в противном случае он может быть полностью доступен любому.

5. Создать PDF в PdfBox

5.1. Вставить текст в PDF

В отличие отiText, библиотекаPdfBox предоставляет API, основанный на управлении потоками. Нет классов вродеChunk /Paragraph и т. Д. КлассPDDocument представляет собой Pdf-представление в памяти, где пользователь записывает данные, манипулируя классомPDPageContentStream.

Давайте посмотрим на пример кода:

PDDocument document = new PDDocument();
PDPage page = new PDPage();
document.addPage(page);

PDPageContentStream contentStream = new PDPageContentStream(document, page);

contentStream.setFont(PDType1Font.COURIER, 12);
contentStream.beginText();
contentStream.showText("Hello World");
contentStream.endText();
contentStream.close();

document.save("pdfBoxHelloWorld.pdf");
document.close();

5.2. Вставка изображения

Вставка изображений проста.

Сначала нам нужно загрузить файл и создатьPDImageXObject, а затем нарисовать его в документе (необходимо указать точные координаты x, y).

Это все:

PDDocument document = new PDDocument();
PDPage page = new PDPage();
document.addPage(page);

Path path = Paths.get(ClassLoader.getSystemResource("Java_logo.png").toURI());
PDPageContentStream contentStream = new PDPageContentStream(document, page);
PDImageXObject image
  = PDImageXObject.createFromFile(path.toAbsolutePath().toString(), document);
contentStream.drawImage(image, 0, 0);
contentStream.close();

document.save("pdfBoxImage.pdf");
document.close();

5.3. Вставка таблицы

К сожалению,PdfBox не предоставляет никаких готовых методов, позволяющих создавать таблицы. Что мы можем сделать в такой ситуации, так это нарисовать ее вручную - буквально, нарисовать каждую линию, пока наш рисунок не станет похожим на нашу воображаемую таблицу.

5.4. Шифрование файлов

БиблиотекаPdfBox предоставляет возможность шифровать и настраивать права доступа к файлам для пользователя. По сравнению сiText, здесь не требуется использовать уже существующий файл, поскольку мы просто используемPDDocument. Разрешения на файл PDF обрабатываются классомAccessPermission, где мы можем установить, сможет ли пользователь изменять, извлекать содержимое или распечатывать файл.

Впоследствии мы создаем объектStandardProtectionPolicy, который добавляет к документу защиту паролем. Мы можем указать два типа пароля. Пароль пользователя, после которого человек сможет открыть файл с примененными правами доступа и паролем владельца (без ограничений для файла):

PDDocument document = new PDDocument();
PDPage page = new PDPage();
document.addPage(page);

AccessPermission accessPermission = new AccessPermission();
accessPermission.setCanPrint(false);
accessPermission.setCanModify(false);

StandardProtectionPolicy standardProtectionPolicy
  = new StandardProtectionPolicy("ownerpass", "userpass", accessPermission);
document.protect(standardProtectionPolicy);
document.save("pdfBoxEncryption.pdf");
document.close();

В нашем примере представлена ​​ситуация, когда пользователь предоставляет пароль пользователя, файл не может быть изменен и распечатан.

6. Выводы

В этом руководстве мы обсудили способы создания PDF-файла в двух популярных библиотеках Java.

Полные примеры можно найти в проектеover on GitHub на основе Maven.