iText + Freemarker實現pdf的導出,支持中文、css以及圖片,頁眉頁腳,頁眉添加圖片

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

前景

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

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

 

本次使用的是Itext5版本,沒有采用最新的官方IText7.

大致實現步驟都是基於文初的那邊文章,只是添加了一個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頁眉中添加圖片了

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章