html转pdf(2)

这次总结一下转pdf,可以设置页眉页脚,水印等

按照之前发过一次转pdf的思路,先是写好html模板,然后用freemarMker填数据得到html的字符串,然后用itext转成pdf,这次主要是添加了页眉页脚的新功能,这里参考了https://blog.youkuaiyun.com/FYWT98/article/details/52189029

新建了一个项目把架包和代码都放在了一起,方便自己以后,需要的可以评论找我发,一套

https://download.youkuaiyun.com/download/hq091117/10937572

首先在接口里:

path:html模板路径,model是填的内容,out是输出流

String content = TemplateUtils.getTranslateTemplate(path, model);
new PdfGenerator().generate(content, out);

 读取模板工具类

public class TemplateUtils {

    public static String getTranslateTemplate(String path, Map<String, Object> model) throws Exception {
        String content = null;

        Configuration config = FreemarkerConfiguration.getConfiguation();
        config.setDefaultEncoding("UTF-8");
        Template template = config.getTemplate(path);
        content = FreeMarkerTemplateUtils.processTemplateIntoString(template, model);
        // StringWriter stringWriter = new StringWriter();
        // BufferedWriter writer = new BufferedWriter(stringWriter);
        // template.setEncoding("UTF-8");
        // template.process(model, writer);
        // content = stringWriter.toString();
        // writer.flush();
        // writer.close();
        return content;
    }

 读取模板所在路径类

public class FreemarkerConfiguration {

    private static Configuration config = null;

    static {
        config = new Configuration();
        config.setClassForTemplateLoading(FreemarkerConfiguration.class, "/template");
    }

    public static Configuration getConfiguation() {
        return config;
    }

}

 转PDF类

package com.zh.audit.confirmation.htmltopdf;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.Charset;

import org.apache.commons.lang3.StringUtils;

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Font;
import com.itextpdf.text.Image;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.tool.xml.Pipeline;
import com.itextpdf.tool.xml.XMLWorker;
import com.itextpdf.tool.xml.XMLWorkerFontProvider;
import com.itextpdf.tool.xml.XMLWorkerHelper;
import com.itextpdf.tool.xml.exceptions.CssResolverException;
import com.itextpdf.tool.xml.html.CssAppliersImpl;
import com.itextpdf.tool.xml.html.Tags;
import com.itextpdf.tool.xml.net.FileRetrieve;
import com.itextpdf.tool.xml.net.ReadingProcessor;
import com.itextpdf.tool.xml.parser.XMLParser;
import com.itextpdf.tool.xml.pipeline.css.CSSResolver;
import com.itextpdf.tool.xml.pipeline.css.CssResolverPipeline;
import com.itextpdf.tool.xml.pipeline.end.PdfWriterPipeline;
import com.itextpdf.tool.xml.pipeline.html.AbstractImageProvider;
import com.itextpdf.tool.xml.pipeline.html.HtmlPipeline;
import com.itextpdf.tool.xml.pipeline.html.HtmlPipelineContext;
import com.itextpdf.tool.xml.pipeline.html.ImageProvider;
import com.itextpdf.tool.xml.pipeline.html.NoImageProviderException;

public class PdfGenerator {

    private static final String CHARSET_NAME = "UTF-8";

    public void generate(String htmlStr, OutputStream out) throws IOException, DocumentException, CssResolverException {

        Document document = new Document(PageSize.A4, 30, 30, 30, 30);
        document.setMargins(30, 30, 30, 30);
        PdfWriter writer = PdfWriter.getInstance(document, out);
        PdfFileExportUtil pdfFileExportUtil = new PdfFileExportUtil();
        writer.setPageEvent(pdfFileExportUtil.new HeadFootInfoPdfPageEvent());
        document.open();

        // html内容解析
        HtmlPipelineContext htmlContext = new HtmlPipelineContext(new CssAppliersImpl(new XMLWorkerFontProvider() {
            @Override
            public Font getFont(String fontName, String encoding, float size, final int style) {
                Font font = null;
                if (fontName == null || "宋体".equals(fontName) || "simsun".equals(fontName)) {
                    // 字体
                    String fontCn = getSIMSUNFont();
                    BaseFont bf;
                    try {
                        // 注意这里有一个,1
                        bf = BaseFont.createFont(fontCn + ",1", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
                        font = new Font(bf, size, style);
                    } catch (DocumentException e) {
                        e.printStackTrace();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }

                }
                return font;
            }
        })) {
            @Override
            public HtmlPipelineContext clone() throws CloneNotSupportedException {
                HtmlPipelineContext context = super.clone();
                try {
                    ImageProvider imageProvider = this.getImageProvider();
                    context.setImageProvider(imageProvider);
                } catch (NoImageProviderException e) {
                }
                return context;
            }
        };

        // 图片解析
        htmlContext.setImageProvider(new AbstractImageProvider() {

            // String rootPath = servletContext.getRealPath("/");

            @Override
            public String getImageRootPath() {
                return "";
            }

            @Override
            public Image retrieve(String src) {
                if (StringUtils.isEmpty(src)) {
                    return null;
                }
                try {
                    // String imageFilePath = new File(rootPath,
                    // src).toURI().toString();
                    Image image = Image.getInstance(src);
                    image.setAbsolutePosition(400, 400);
                    if (image != null) {
                        store(src, image);
                        return image;
                    }
                } catch (Throwable e) {
                    e.printStackTrace();
                }
                return super.retrieve(src);
            }
        });
        htmlContext.setAcceptUnknown(true).autoBookmark(true).setTagFactory(Tags.getHtmlTagProcessorFactory());

        // css解析
        CSSResolver cssResolver = XMLWorkerHelper.getInstance().getDefaultCssResolver(true);
        cssResolver.setFileRetrieve(new FileRetrieve() {
            @Override
            public void processFromStream(InputStream in, ReadingProcessor processor) {
                try {
                    InputStreamReader reader = new InputStreamReader(in, CHARSET_NAME);
                    int i = -1;
                    while (-1 != (i = reader.read())) {
                        processor.process(i);
                    }
                } catch (Throwable e) {

                }
            }

            // 解析href
            @Override
            public void processFromHref(String href, ReadingProcessor processor) throws IOException {
                URL url = new URL(href);
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                conn.setRequestMethod("GET");
                conn.setConnectTimeout(5 * 1000);
                InputStream is = conn.getInputStream();
                InputStreamReader reader = new InputStreamReader(is, CHARSET_NAME);
                try {
                    int i = -1;
                    while (-1 != (i = reader.read())) {
                        processor.process(i);
                    }
                } catch (Throwable e) {
                    e.printStackTrace();
                }
            }
        });
        // cssResolver.addCss(".div-0{font-size: 36px; text-align:
        // center;}",true);
        HtmlPipeline htmlPipeline = new HtmlPipeline(htmlContext, new PdfWriterPipeline(document, writer));
        Pipeline<?> pipeline = new CssResolverPipeline(cssResolver, htmlPipeline);
        XMLWorker worker = new XMLWorker(pipeline, true);
        XMLParser parser = new XMLParser(true, worker, Charset.forName(CHARSET_NAME));
        InputStream inputStream = new ByteArrayInputStream(htmlStr.getBytes(CHARSET_NAME));
        try {
            parser.parse(inputStream, Charset.forName(CHARSET_NAME));
        } catch (Throwable e) {
            e.printStackTrace();
        }
        document.close();
    }

    /**
     * 获取中文字体位置
     *
     * @return
     */
    private String getSIMSUNFont() {

        String font = this.getClass().getResource("/").getPath() + "template/SIMSUN.TTC";
        // String font = "D:/tmp/SIMSUN.TTC";
        // System.out.println(font);
        if (!new File(font).exists()) {
            throw new RuntimeException("字体文件不存在,影响导出pdf中文显示!" + font);
        }

        return font;
    }
}

 操作PDF的工具类

package com.zh.audit.confirmation.htmltopdf;

import java.io.IOException;

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.Phrase;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.ColumnText;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfGState;
import com.itextpdf.text.pdf.PdfPageEventHelper;
import com.itextpdf.text.pdf.PdfWriter;

public class PdfFileExportUtil {

    private static Font pdf8Font = null;
    private static Font pdf20Font = null;

    /**
     * 获取中文字符集且是8号字体,常用作表格内容的字体格式
     * 
     * @return
     * @throws DocumentException
     * @throws IOException
     */
    public static Font getChinese8Font() throws DocumentException, IOException {
        if (pdf8Font == null) {
            // 设置中文字体和字体样式 
            BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
            pdf8Font = new Font(bfChinese, 10, Font.NORMAL);
        }
        return pdf8Font;
    }

    /**
     * 获取中文字符集且是8号字体,常用作文字水印信息
     * 
     * @return
     * @throws DocumentException
     * @throws IOException
     */
    public static Font getChinese20Font() throws DocumentException, IOException {
        if (pdf20Font == null) {
            // 设置中文字体和字体样式
            BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
            pdf20Font = new Font(bfChinese, 20, Font.BOLD);
        }
        return pdf20Font;
    }

    /**
     * 设置只读
     * 
     * @param pdfWriter
     * @return
     * @throws DocumentException
     */
    public static PdfWriter setReadOnlyPDFFile(PdfWriter pdfWriter) throws DocumentException {
        pdfWriter.setEncryption(null, null, PdfWriter.ALLOW_PRINTING, PdfWriter.STANDARD_ENCRYPTION_128);
        return pdfWriter;
    }

    /**
     * 图片水印
     * 
     * @param waterMarkImage
     * @param xPosition
     * @param yPosition
     * @return
     */
    public static Image getWaterMarkImage(Image waterMarkImage, float xPosition, float yPosition) {
        waterMarkImage.setAbsolutePosition(xPosition, yPosition);// 坐标 
        waterMarkImage.setRotation(-20);// 旋转弧度 
        waterMarkImage.setRotationDegrees(-45);// 旋转角度 
        waterMarkImage.scalePercent(100);// 依照比例缩放 
        return waterMarkImage;
    }

    /**
     * 文本水印
     * 
     * @author wangjing
     *
     */
    class TextWaterMarkPdfPageEvent extends PdfPageEventHelper {
        private String waterMarkText;

        public TextWaterMarkPdfPageEvent(String waterMarkText) {
            this.waterMarkText = waterMarkText;
        }

        public void onEndPage(PdfWriter writer, Document document) {
            try {
                float pageWidth = document.right() + document.left();// 获取pdf内容正文页面宽度
                float pageHeight = document.top() + document.bottom();// 获取pdf内容正文页面高度
                // 设置水印字体格式  
                Font waterMarkFont = PdfFileExportUtil.getChinese20Font();
                PdfContentByte waterMarkPdfContent = writer.getDirectContentUnder();
                Phrase phrase = new Phrase(waterMarkText, waterMarkFont);
                ColumnText.showTextAligned(waterMarkPdfContent, Element.ALIGN_CENTER, phrase, pageWidth * 0.25f,
                        pageHeight * 0.2f, 45);
                ColumnText.showTextAligned(waterMarkPdfContent, Element.ALIGN_CENTER, phrase, pageWidth * 0.25f,
                        pageHeight * 0.5f, 45);
                ColumnText.showTextAligned(waterMarkPdfContent, Element.ALIGN_CENTER, phrase, pageWidth * 0.25f,
                        pageHeight * 0.8f, 45);
                ColumnText.showTextAligned(waterMarkPdfContent, Element.ALIGN_CENTER, phrase, pageWidth * 0.65f,
                        pageHeight * 0.2f, 45);
                ColumnText.showTextAligned(waterMarkPdfContent, Element.ALIGN_CENTER, phrase, pageWidth * 0.65f,
                        pageHeight * 0.5f, 45);
                ColumnText.showTextAligned(waterMarkPdfContent, Element.ALIGN_CENTER, phrase, pageWidth * 0.65f,
                        pageHeight * 0.8f, 45);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        /**
         * 图片水印
         * 
         * @author wangjing
         *
         */
        class PictureWaterMarkPdfPageEvent extends PdfPageEventHelper {
            private String waterMarkFullFilePath;
            private Image waterMarkImage;

            public PictureWaterMarkPdfPageEvent(String waterMarkFullFilePath) {
                this.waterMarkFullFilePath = waterMarkFullFilePath;
            }

            public void onEndPage(PdfWriter writer, Document document) {
                try {
                    float pageWidth = document.right() + document.left();// 获取pdf内容正文页面宽度
                    float pageHeight = document.top() + document.bottom();// 获取pdf内容正文页面高度
                    PdfContentByte waterMarkPdfContent = writer.getDirectContentUnder();
                    // 仅设置一个图片实例对象,整个PDF文档只应用一个图片对象,极大减少因为增加图片水印导致PDF文档大小增加
                    if (waterMarkImage == null) {
                        waterMarkImage = Image.getInstance(waterMarkFullFilePath);
                    }
                    // 添加水印图片,文档正文内容采用横向三列,竖向两列模式增加图片水印  
                    waterMarkPdfContent
                            .addImage(getWaterMarkImage(waterMarkImage, pageWidth * 0.2f, pageHeight * 0.1f));
                    waterMarkPdfContent
                            .addImage(getWaterMarkImage(waterMarkImage, pageWidth * 0.2f, pageHeight * 0.4f));
                    waterMarkPdfContent
                            .addImage(getWaterMarkImage(waterMarkImage, pageWidth * 0.2f, pageHeight * 0.7f));
                    waterMarkPdfContent
                            .addImage(getWaterMarkImage(waterMarkImage, pageWidth * 0.6f, pageHeight * 0.1f));
                    waterMarkPdfContent
                            .addImage(getWaterMarkImage(waterMarkImage, pageWidth * 0.6f, pageHeight * 0.4f));
                    waterMarkPdfContent
                            .addImage(getWaterMarkImage(waterMarkImage, pageWidth * 0.6f, pageHeight * 0.7f));
                    PdfGState gs = new PdfGState();
                    gs.setFillOpacity(0.2f);// 设置透明度为0.2  
                    waterMarkPdfContent.setGState(gs);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 页脚(第几页)
     * 
     * @author wangjing
     *
     */
    class HeadFootInfoPdfPageEvent extends PdfPageEventHelper {
        public HeadFootInfoPdfPageEvent() {
        }

        public void onEndPage(PdfWriter writer, Document document) {
            try {
                PdfContentByte headAndFootPdfContent = writer.getDirectContent();
                headAndFootPdfContent.saveState();
                headAndFootPdfContent.beginText();
                BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
                headAndFootPdfContent.setFontAndSize(bfChinese, 15);
                // 文档页头信息设置  
                // float x = document.top(-20);
                // headAndFootPdfContent.showTextAligned(PdfContentByte.ALIGN_RIGHT,
                // "-", document.right(), x, 0);
                // 文档页脚信息设置  
                float y = document.bottom(-20);
                // 页脚信息左面
                // headAndFootPdfContent.showTextAligned(PdfContentByte.ALIGN_LEFT,
                // "--", document.left(), y, 0);
                // 页脚信息中间  
                headAndFootPdfContent.showTextAligned(PdfContentByte.ALIGN_CENTER, "第" + writer.getPageNumber() + "页",
                        (document.right() + document.left()) / 2, y, 0);
                // 页脚信息右面
                // headAndFootPdfContent.showTextAligned(PdfContentByte.ALIGN_RIGHT,
                // "--", document.right(), y, 0);
                headAndFootPdfContent.endText();
                headAndFootPdfContent.restoreState();
            } catch (DocumentException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值