1. 程式人生 > >java根據模板匯出pdf(動態增加模板頁數)

java根據模板匯出pdf(動態增加模板頁數)

這兩天碰到了一個根據模板匯出pdf的需求,研究了幾天以後,發現網上的資料不太齊全,主要是沒找到既根據模板匯出,又可以動態增加頁數的例子。只能通過各種資料結合來實現這個需求了(其實是懶得看iText英文文件,這個以後得改過來)。 下面先來說下pdf匯出主要的兩種方式: 1.直接使用iText的api,寫出原生的pdf文件,但是樣式和排版很難控制,比較方便的是,可以動態的新增文件資料,還可以增加頁數等操作。關於樣式和排版可以通過結合XmlWorker,從HTML模板生成PDF。 2.根據pdf模板匯出,這裡會涉及到使用adobe acrobat這個軟體。通過adobe acrobat來製作表單域,然後在應用程式裡動態向表單域新增資料。 (1)在adobe acrobat中開啟一個pdf文件,然後點選右側的“準備表單”,選擇檔案後點擊“開始” 圖片步驟為: 在這裡插入圖片描述

在這裡插入圖片描述 (2).在頁面上新建表單域,可以通過右鍵-屬性,修改表單域的設定,這裡新建了兩個name為“title”和“img”的文字域 在這裡插入圖片描述 在這裡插入圖片描述 (3).將設定了表單域的pdf文件儲存即可 3.現在就是開始寫java程式碼了,首先需要在pom檔案裡引入兩個itext的jar包,如下所示:

        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itextpdf</artifactId>
            <version>5.5.6</version>
        </dependency>
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itext-asian</artifactId>
        </dependency>

(1)多頁匯出,包含圖片。如果匯出的中文無法顯示,需要重新設定字型。

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Image;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.*;

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

public class PdfTest {
    // 利用模板生成pdf
    public static void fillTemplate() {
        // 原pdf模板路徑
        String templatePath = "D:/old.pdf";
        // 生成的新檔案路徑
        String newPDFPath = "D:/new.pdf";
        //圖片路徑
        String imgPath = "D:/test.jpg";
        FileOutputStream out;
        int num = 2;//頁數
        ByteArrayOutputStream bos[] = new ByteArrayOutputStream[num];
        try {
            out = new FileOutputStream(newPDFPath);// 輸出流
            Document doc = new Document();   //新建一個文件
            PdfCopy copy = new PdfCopy(doc, out); //用於儲存原頁面內容,然後輸出
            doc.open();

            for (int i = 0; i < num; i++) {
                bos[i] = new ByteArrayOutputStream();
                PdfReader reader = new PdfReader(templatePath);// 讀取pdf模板
                PdfStamper stamper = new PdfStamper(reader, bos[i]); //生成輸出流
                AcroFields form = stamper.getAcroFields(); //獲取文字域
                form.setField("title", "這是標題");

                int pageNo = form.getFieldPositions("img").get(0).page;
                Rectangle rectangle = form.getFieldPositions("img").get(0).position;
                float x = rectangle.getLeft();
                float y = rectangle.getBottom();
                //根據路徑讀取圖片
                Image image = Image.getInstance("D:/test.jpg");
                //獲取圖片頁面
                PdfContentByte under = stamper.getOverContent(pageNo);
                //圖片大小自適應
                image.scaleToFit(rectangle.getWidth(), rectangle.getHeight());
                //新增圖片
                image.setAbsolutePosition(x, y);
                under.addImage(image);
                stamper.setFormFlattening(true);// 如果為false那麼生成的PDF檔案還能編輯,一定要設為true
                stamper.close();

            }
            PdfImportedPage page = null;
            for (int i = 0; i < num; i++) {
                page = copy.getImportedPage(new PdfReader(bos[i].toByteArray()), i + 1);
                copy.addPage(page);
            }
            doc.close();
            out.close();
        } catch (IOException e) {
            System.out.println("匯出異常");
        } catch (DocumentException e) {
            System.out.println("文件異常");
        }

    }

    public static void main(String[] args) {
        fillTemplate();
    }
}

(2)此時的需求是需要根據應用程式,動態複製第二頁的模板,那麼程式碼改為下面這種

// 利用模板生成pdf
    public static void fillTemplate() {
        // 原pdf模板路徑
        String templatePath = "D:/old.pdf";
        // 生成的新檔案路徑
        String newPDFPath = "D:/new.pdf";
        //圖片路徑
        String imgPath = "D:/test.jpg";
        FileOutputStream out;
        int num = 4;//頁數
        ByteArrayOutputStream bos[] = new ByteArrayOutputStream[num];
        try {
            out = new FileOutputStream(newPDFPath);// 輸出流
            Document doc = new Document();   //新建一個文件
            PdfCopy copy = new PdfCopy(doc, out); //用於儲存原頁面內容,然後輸出
            doc.open();

            for (int i = 0; i < 2; i++) {
                bos[i] = new ByteArrayOutputStream();
                PdfReader reader = new PdfReader(templatePath);// 讀取pdf模板
                PdfStamper stamper = new PdfStamper(reader, bos[i]); //生成輸出流
                AcroFields form = stamper.getAcroFields(); //獲取文字域
                form.setField("title", "這是標題");

                int pageNo = form.getFieldPositions("img").get(0).page;
                Rectangle rectangle = form.getFieldPositions("img").get(0).position;
                float x = rectangle.getLeft();
                float y = rectangle.getBottom();
                //根據路徑讀取圖片
                Image image = Image.getInstance("D:/test.jpg");
                //獲取圖片頁面
                PdfContentByte under = stamper.getOverContent(pageNo);
                //圖片大小自適應
                image.scaleToFit(rectangle.getWidth(), rectangle.getHeight());
                //新增圖片
                image.setAbsolutePosition(x, y);
                under.addImage(image);
                stamper.setFormFlattening(false);// 如果為false那麼生成的PDF檔案還能編輯,一定要設為true
                stamper.close();

            }
            //將之前的兩次輸出
            PdfImportedPage page = null;
            for (int i = 0; i < 2; i++) {
                page = copy.getImportedPage(new PdfReader(bos[i].toByteArray()), i + 1);
                copy.addPage(page);
            }
            //複製兩次
            for (int j=0;j<2;j++){
                PdfReader reader = new PdfReader(templatePath);// 重新讀取pdf模板
                bos[j]=new ByteArrayOutputStream();
                reader.selectPages("2-2");//擷取模板的第二頁
                PdfStamper stamper = new PdfStamper(reader, bos[j]);
                AcroFields fields = stamper.getAcroFields();
                fields.setField("img", "這是第"+j+"張圖片");
                page = copy.getImportedPage(reader, 1);//輸出當前頁
                copy.addPage(page);
            }

            doc.close();
            out.close();
        } catch (IOException e) {
            System.out.println("匯出異常");
        } catch (DocumentException e) {
            System.out.println("文件異常");
        }