1. 程式人生 > >iText + Freemarker實現pdf的匯出,支援中文、css以及圖片,頁首頁尾,頁首新增圖片

iText + Freemarker實現pdf的匯出,支援中文、css以及圖片,頁首頁尾,頁首新增圖片

 

  本文為了記錄自己的實現過程,具體的實現步驟是參考博文 https://www.cnblogs.com/youzhibing/p/7692366.html 來實現的,只是在他的基礎上添加了頁首頁尾及頁首圖片

 

 

 

  原來是決定採用wkhtmlToPdf將html頁面轉換為pdf,而且html樣式儲存的還挺好,但是最後嘗試下來發現,他轉換不了我們框架中的html頁面,將框架中的html頁面地址進行轉換總是會轉換成首頁的圖片,多次查詢無果,最終放棄了,改換成itext工具。

  由於我們的需求中要求有頁首和頁尾,並且頁首中需要有logo圖片,所以在網上也是找了很多部落格,嘗試了網上的很多種方法都不能使用,不知道是我這邊的問題還是博主們都沒有進行測試就把文章發出來了,最後實在找不到能用的資訊我就開始了自己的探索,最終經過我自己的探索,實現了頁首中新增圖片的功能,特此記錄一下。

 

大致實現步驟都是基於文初的那邊文章,只是添加了一個Build類繼承他的PdfPageEventHelper,具體程式碼如下:

 

package com.tzCloud.core.utils;

import com.itextpdf.text.Chunk;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.Image;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.ColumnText;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfPageEventHelper;
import com.itextpdf.text.pdf.PdfTemplate;
import com.itextpdf.text.pdf.PdfWriter;

import java.io.IOException;

/**
 * PDF匯出頁首、頁尾、水印等處理類
 * 設定頁面附加屬性
 *
 * @author LiuYu
 * @date 2019/11/5 16:45
 */
public class PDFBuilder extends PdfPageEventHelper {

    /**
     * 頁首
     */
    public String header = "itext測試頁首";

    /**
     * 文件字型大小,頁尾頁首最好和文字大小一致
     */
    public int presentFontSize = 12;

    /**
     * 文件頁面大小,最好前面傳入,否則預設為A4紙張
     */
    public Rectangle pageSize = PageSize.A4;

    /**
     * 模板
      */
    public PdfTemplate total;

    /**
     * 基礎字型物件
     */
    public BaseFont bf = null;

    /**
     * 利用基礎字型生成的字型物件,一般用於生成中文文字
     */
    public Font fontDetail = null;


    public void setHeader(String header) {
        this.header = header;
    }

    public void setPresentFontSize(int presentFontSize) {
        this.presentFontSize = presentFontSize;
    }

    /**
     *
     * TODO 文件開啟時建立模板
     *
     * @see PdfPageEventHelper#onOpenDocument(PdfWriter,
     *      Document)
     */
    @Override
    public void onOpenDocument(PdfWriter writer, Document document) {
        // 共 頁 的矩形的長寬高
        total = writer.getDirectContent().createTemplate(50, 50);
    }

    /**
     *
     * TODO 關閉每頁的時候,寫入頁首,寫入'第幾頁共'這幾個字。
     *
     * @see PdfPageEventHelper#onEndPage(PdfWriter,
     *      Document)
     */
    @Override
    public void onEndPage(PdfWriter writer, Document document) {
        this.addPage(writer, document);
        //this.addWatermark(writer);
    }

    //加分頁
    public void addPage(PdfWriter writer, Document document){

        // 首頁不新增頁首和頁尾
        if(writer.getPageNumber() == 1){
            // 用於新增首頁的封面背景圖,這裡首頁添加了兩張背景圖,一個從左上角一個從左下角,具體位置可修改下面的位置資訊
            try {
                // PDF 首頁頂部背景圖
                Image image = Image.getInstance("https://******");
                 // 設定圖片的位置 圖片位置左邊是左下角為0,0
                image.setAbsolutePosition(0, 441);
                 // 設定圖片的大小
                image.scaleAbsolute(570, 400);

                // PDF 首頁底部背景圖
                Image instance = Image.getInstance("https://*****");
                instance.setAbsolutePosition(0, 0);
                instance.scaleAbsolute(595, 260);

                document.add(image);
                document.add(instance);
            } catch (IOException | DocumentException e) {
                e.printStackTrace();
            }

            return;
        }

        //設定分頁頁首頁尾字型
        Image image = null;
        try {
            // 頁首logo圖片例項
            image = Image.getInstance("https://******");
            if (bf == null) {
                bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", false);
            }
            if (fontDetail == null) {
                // 資料體字型
                fontDetail = new Font(bf, presentFontSize, Font.NORMAL);
            }
        } catch (DocumentException | IOException e) {
            e.printStackTrace();
        }

        PdfContentByte directContent = writer.getDirectContent();


        //1、生成右側頁首
        // document.right(-20)  方法設定頁首的左右間距
        // document.top(+20)  方法設定頁首的上下間距
        ColumnText.showTextAligned(directContent,
                Element.ALIGN_RIGHT, new Phrase("聯絡電話:400-000-0000", fontDetail),
                document.right(), document.top(), 0);

        //  !!!! 最重要的是這個, 如果頁首需要設定圖片的話,需要在Phrase物件中新增一個Chunk物件,在Chunk物件中新增圖片資訊即可
        Phrase p1 = new Phrase("", fontDetail);
        p1.add(new Chunk(image, 0, -30));
        // 1、寫入左側頁首
        ColumnText.showTextAligned(directContent,
                Element.ALIGN_LEFT, p1,
                document.left(), document.top(-20), 0);

        // 2、生成右側頁尾
        ColumnText.showTextAligned(directContent,
                Element.ALIGN_RIGHT, new Phrase(String.valueOf(document.getPageNumber() - 1), fontDetail),
                document.right(), document.bottom(-20), 0);

        // 2、生成左側頁尾
        ColumnText.showTextAligned(directContent,
                Element.ALIGN_LEFT, new Phrase("******有限公司", fontDetail),
                document.left(), document.bottom(-20), 0);


    }

    /**
     * 加水印
     */
    public void addWatermark(PdfWriter writer){
        // 水印圖片
        Image image;
        try {
            image = Image.getInstance("./web/images/001.jpg");
            PdfContentByte content = writer.getDirectContentUnder();
            content.beginText();
            // 開始寫入水印
            for(int k=0;k<5;k++){
                for (int j = 0; j <4; j++) {
                    image.setAbsolutePosition(150*j,170*k);
                    content.addImage(image);
                }
            }
            content.endText();
        } catch (IOException | DocumentException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    /**
     *
     * TODO 關閉文件時,替換模板,完成整個頁首頁尾元件
     *
     * @see PdfPageEventHelper#onCloseDocument(PdfWriter,
     *      Document)
     */
    @Override
    public void onCloseDocument(PdfWriter writer, Document document) {
        // 7.最後一步了,就是關閉文件的時候,將模板替換成實際的 Y 值,至此,page x of y 製作完畢,完美相容各種文件size。
        total.beginText();
        // 生成的模版的字型、顏色
        total.setFontAndSize(bf, presentFontSize);
        //頁尾內容拼接  如  第1頁/共2頁
        String foot2 = " " + (writer.getPageNumber()) + " 頁";
        // 模版顯示的內容
        total.showText(foot2);
        total.endText();
        total.closePath();
    }
}

 

具體的對PDF每頁的操作都可以在這個類中進行實現,通過document的getPageNumber方法可以判斷當前在PDF的第幾頁,然後就可以進行具體的操作了, 就例如上面的程式碼在首頁可以新增背景圖等操作。

  至此就可以實現在PDF頁首中新增圖片了