01.在Java中如何創建PDF文件


1.簡介

在這篇快速文章中,我們將重點介紹基於流行的iText和PdfBox庫從頭開始創建 PDF 文檔。

2. Maven 依賴

<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>itextpdf</artifactId>
    <version>5.5.10</version>
</dependency>
<dependency>
    <groupId>org.apache.pdfbox</groupId>
    <artifactId>pdfbox</artifactId>
    <version>2.0.4</version>
</dependency>

可以在這里找到該庫的最新版本:iTextPdfBox

如果需要加密我們的文件,則需要添加一個額外的依賴項。The Bounty Castle Provider。軟件包包含加密算法的實現,並且兩個庫都需要:

<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcprov-jdk15on</artifactId>
    <version>1.56</version>
</dependency>

可以在這里找到該庫的最新版本:The Bounty Castle Provider

3.概述

iText 和 PdfBox 都是用於創建/操作 pdf 文件的 Java 庫。盡管這些庫的最終輸出是相同的,但它們的操作方式略有不同。讓我們看看它們。

4.在 IText 中創建 Pdf

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();

使用 iText 庫創建 pdf 的基礎是操縱在 Document 中實現 Elements 接口的對象(在 5.5.10 版中,其中 45 種實現)。

可以添加到文檔中並使用的最小元素稱為 Chunk,基本上是一個帶有應用字體的字符串。

此外,Chunk 可以與其他元素(如 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.在 PdfBox 中創建 Pdf

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.結論

在本教程中,我們討論了在兩個流行的 Java 庫中創建 pdf 文件的方法。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM