JAVA HTML 转 PDF和增加水印

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>
  • 39
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是一个使用iText7将HTML换为PDF并添页数和水印的简单示例: ```java import com.itextpdf.html2pdf.ConverterProperties; import com.itextpdf.html2pdf.HtmlConverter; import com.itextpdf.kernel.colors.ColorConstants; import com.itextpdf.kernel.font.PdfFont; import com.itextpdf.kernel.font.PdfFontFactory; import com.itextpdf.kernel.geom.Rectangle; 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.xobject.PdfFormXObject; import java.io.File; import java.io.IOException; public class HtmlToPdfConverter { public static void main(String[] args) throws IOException { String html = "<html><body><h1>Hello, World!</h1></body></html>"; String pdfPath = "output.pdf"; PdfWriter writer = new PdfWriter(pdfPath); PdfDocument pdfDoc = new PdfDocument(writer); pdfDoc.setDefaultPageSize(new Rectangle(PageSize.A4.getLeft(), PageSize.A4.getBottom(), PageSize.A4.getRight(), PageSize.A4.getTop())); PdfFont font = PdfFontFactory.createFont("path/to/font.ttf", PdfEncodings.IDENTITY_H, true); PdfCanvas canvas = new PdfCanvas(pdfDoc.addNewPage()); canvas.beginText() .setFontAndSize(font, 12) .moveText(pdfDoc.getDefaultPageSize().getRight() - 72, 36) .showText("Page 1") .endText(); ConverterProperties props = new ConverterProperties(); HtmlConverter.convertToPdf(html, pdfDoc, props); int n = pdfDoc.getNumberOfPages(); for (int i = 2; i <= n; i++) { PdfPage page = pdfDoc.getPage(i); canvas = new PdfCanvas(page); canvas.beginText() .setFontAndSize(font, 12) .moveText(pdfDoc.getDefaultPageSize().getRight() - 72, 36) .showText(String.format("Page %d", i)) .endText(); } PdfFormXObject watermark = new PdfFormXObject(new Rectangle(0, 0, 100, 100)); canvas = new PdfCanvas(watermark, pdfDoc); canvas.setFillColor(ColorConstants.LIGHT_GRAY); canvas.setStrokeColor(ColorConstants.LIGHT_GRAY); canvas.rectangle(0, 0, 100, 100); canvas.fill(); canvas.beginText() .setFontAndSize(font, 24) .moveText(20, 50) .showText("Confidential") .endText(); for (int i = 1; i <= n; i++) { PdfPage page = pdfDoc.getPage(i); canvas = new PdfCanvas(page); canvas.addXObject(watermark, 0, 0); } pdfDoc.close(); } } ``` 在上面的示例中,我们首先创建一个PdfWriter和PdfDocument对象,然后设置默认页面大小为A4纸张大小。接下来,我们添第一页,并在页面右下角添“Page 1”文本。然后使用iText7的HtmlConverter将HTML字符串换为PDF文档。使用循环遍历文档中的每个页面,并在每个页面的右下角添页码。最后,我们创建一个PdfFormXObject对象,添水印文本“Confidential”,并将其添到每个页面中。 请注意,上面的示例中的代码片段是未经测试的,仅供参考。您需要根据您自己的需求进行修改和调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值