首页 前端知识 JAVA HTML 转 PDF和增加水印

JAVA HTML 转 PDF和增加水印

2024-08-12 10:08:40 前端知识 前端哥 927 655 我要收藏

1、依赖 gradle

implementation 'com.itextpdf:html2pdf:5.0.0'

2、JAVA代码

import cn.hutool.core.io.FileUtil;
import com.itextpdf.html2pdf.ConverterProperties;
import com.itextpdf.html2pdf.HtmlConverter;
import com.itextpdf.kernel.events.Event;
import com.itextpdf.kernel.events.IEventHandler;
import com.itextpdf.kernel.events.PdfDocumentEvent;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfPage;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
import com.itextpdf.kernel.pdf.extgstate.PdfExtGState;
import com.itextpdf.layout.font.FontProvider;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.Version;
import lombok.extern.slf4j.Slf4j;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.util.Map;

/**
 * @author 01418708
 */
@Slf4j
public class PdfGenerator {

    private static final Configuration CFG;

    static {
        // 配置Freemarker
        CFG = new Configuration(new Version("2.3.30"));
        CFG.setDefaultEncoding("UTF-8");
        // 设置模板文件的路径
        CFG.setClassForTemplateLoading(PdfGenerator.class, "/pdf/template");
    }

    /**
     * 获取pdf文本
     *
     * @param dataModel
     * @param templateName
     * @return
     */
    public static byte[] getPdfByte(Map<String, Object> dataModel, String templateName) throws Exception {
        try {
            // 加载Freemarker模板
            Template template = CFG.getTemplate(templateName + ".ftl");
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            // 使用iText生成PDF
            PdfWriter writer = new PdfWriter(outputStream);
            PdfDocument pdf = new PdfDocument(writer);
            pdf.addEventHandler(PdfDocumentEvent.START_PAGE, new Watermark("aaaa"));
            // 处理模板并生成内容
            StringWriter htmlWriter = new StringWriter();
            template.process(dataModel, htmlWriter);
            String html = htmlWriter.toString();

            ConverterProperties converterProperties = new ConverterProperties();
            FontProvider fontProvider = new FontProvider();

            fontProvider.addFont(PdfFontFactory.createFont("/pdf/font/msyh.ttc,1", "Identity-H").getFontProgram(), "Identity-H");
            converterProperties.setFontProvider(fontProvider);

            HtmlConverter.convertToPdf(html, pdf, converterProperties);

            return outputStream.toByteArray();
        } catch (Exception e) {
            log.error("PDF 生成失败:", e);
            throw e;
        }
    }

    static class Watermark implements IEventHandler {

        private final String text;

        public Watermark(String text) {
            this.text = text;
        }

        @Override
        public void handleEvent(Event event) {
            PdfDocumentEvent docEvent = (PdfDocumentEvent) event;
            PdfPage page = docEvent.getPage();
            PdfDocument document = docEvent.getDocument();

            PdfCanvas canvas = new PdfCanvas(page.newContentStreamBefore(), page.getResources(), document);
            try {
                PdfExtGState extGState = new PdfExtGState();
                extGState.setFillOpacity(0.05f); // 设置填充透明度为0.05
                double alpha = Math.toRadians(15); // 倾斜角度
                double tanAlpha = Math.tan(alpha);
                //可根据页面宽高设置水印
                for (int i = 0; i < 10; i++) {
                    canvas.saveState()
                            .concatMatrix(1, tanAlpha, 0, 1, 0, 0)
                            .beginText()
                            .resetFillColorGray()
                            .setExtGState(extGState)
                            .moveText(200, 400 + i * 20)
                            .setFontAndSize(PdfFontFactory.createFont("/pdf/font/msyh.ttc,1", "Identity-H"), 10)
                            .showText(text)
                            .endText()
                            .restoreState();
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

    public static void main(String[] args) throws SystemException {
        byte[] pdfByte = getPdfByte(null, "ReceiptTemplate");
        FileUtil.writeBytes(pdfByte, new File("out.pdf"));
    }
}

ftl 模板

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        @page {
            @bottom-center {
                content: counter(page) "/" counter(pages);
                font-size: 10px;
            }
        }

        * {
            padding: 0;
            margin: 0;
            box-sizing: border-box;
            font-size: 10px;
            color: #333;
        }

        .inner-Wrap {
            width: 535px;
            margin: 0 auto;
        }

        /* title start */
        .title {
            padding: 30px 0 13px;
            text-align: center;
            font-size: 17px;
        }

        /* title end */

        .line {
            width: 100%;
            height: 1px;
            background-color: #000;
        }

        /* info-box start */
        .info-box {
            padding: 20px 0 10px;
        }

        .info-tag-flex1 {
            display: flex;
        }

        .info-tag-flex1-child1 {
            width: 300px;
        }

        .info-tag-flex1-child2 {
        }

        .info-tag-flex2 {
            display: flex;
            flex-direction: column;
            justify-content: space-between;
        }

        .info-box .info-tag-box {
            display: flex;
            align-items: flex-start;
            margin-bottom: 10px;
        }

        .info-box .info-tag-box .info-tag {
            min-width: 122px;
        }

        .info-box .info-tag-box .info-tag-1 {
            width: 75px!important;
        }


        /* info-box end */

        /* table start */
        .table {
            width: 100%;
            border-collapse: collapse;
            border: 1px solid #000;
        }

        .table tr {
            page-break-inside: avoid;
            page-break-after: auto;
        }

        .table tr td {
            border: 1px solid #000;
            text-align: center;
        }

        .table .td-title {
            height: 30px;
            font-size: 15px;
        }

        .table .td1 {
            height: 30px;
            width: 30px;
        }

        .table .td2 {
            height: 30px;
            width: 92px;
        }

        .table .td3 {
            height: 30px;
            width: 185px;
        }

        .table .td4 {
            height: 30px;
            width: 30px;
        }

        .table .td5 {
            height: 30px;
        }

        .table .td6 {
            height: 30px;
        }

        .goods-td {
            height: 25px;
        }

        .total {
            height: 30px;
        }

        .table-remark-box {
            min-height: 100px;
            text-align: left;
            padding: 10px;
        }

        .table-remark-tag {
        }

        .table-remark-sign {
            margin-top: 20px;
            margin-left: 206px;
        }
        .table-remark-desc{
            line-height: 19px;
        }
        .table-remark-warn{
            line-height: 19px;
        }
        tr, td, th, tbody, thead, tfoot {
            page-break-inside: avoid;
        }

        /* table end */
    </style>
</head>

<body>
<div class="inner-Wrap">
    <div class="title">222222</div>
    <div class="line"></div>
    <div class="info-box">
        <div class="info-tag-flex1">
            <div class="info-tag-box info-tag-flex1-child1">
                <div class="info-tag">33333:</div>
                <div class="info-desc">${orderId}</div>
            </div>
         
        </div>
       
    <table class="table">
        <thead>
        <tr>
            <td colspan="6" class="td-title">333333</td>
        </tr>
        <tr>
            <td class="td1">111</td>
            <td class="td2">222</td>
            <td class="td3">333</td>
            <td class="td4">444</td>
            <td class="td5">555</td>
            <td class="td6">P66</td>
        </tr>
        </thead>
        <tbody>
        <#if skuList?has_content>
            <#list skuList as sku>
                <tr>
                    <td class="goods-td">${sku_index + 1}</td>
                    <td class="goods-td">${sku.skuNo!"-"}</td>
                    <td class="goods-td">${sku.skuName!"-"}</td>
                    <td class="goods-td">${sku.skuCount!"-"}</td>
                    <td class="goods-td">${sku.use!"-"}</td>
                    <td class="goods-td">${sku.poNo!"-"}</td>
                </tr>
            </#list>
        </#if>

        <tr>
            <td colspan="3" class="total">汇总</td>
            <td>${skuListTotal}</td>
            <td></td>
            <td></td>
        </tr>
      
        </tbody>
    </table>
</div>
</body>
转载请注明出处或者链接地址:https://www.qianduange.cn//article/15328.html
标签
评论
发布的文章

jQuery3 学习手册(三)

2024-08-18 22:08:04

vue和jQuery有什么区别

2024-04-29 11:04:47

推荐项目:jQuery.Gantt

2024-08-18 22:08:37

jQuery UI 秘籍(一)

2024-08-18 22:08:15

jQuery详解

2024-04-29 11:04:38

echarts饼图点击图例问题

2024-08-18 22:08:48

echarts天气折线图

2024-08-18 22:08:46

大家推荐的文章
会员中心 联系我 留言建议 回顶部
复制成功!