基于itext5动态生成pdf带分页,自定义字体

话不多说直接撸代码:
最终效果图:
基于itext5动态生成pdf带分页,自定义字体_第1张图片

在这里插入代码片
 <dependency>
                <groupId>com.itextpdf</groupId>
                <artifactId>itextpdf</artifactId>
                <version>5.5.9</version>
            </dependency>
            <dependency>
                <groupId>com.itextpdf.tool</groupId>
                <artifactId>xmlworker</artifactId>
                <version>5.5.9</version>
            </dependency>

            <dependency>
                <groupId>com.itextpdf</groupId>
                <artifactId>itext-asian</artifactId>
                <version>5.2.0</version>
            </dependency>
    
            <dependency>
                <groupId>org.xhtmlrenderer</groupId>
                <artifactId>flying-saucer-pdf-itext5</artifactId>
                <version>9.0.3</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/freemarker/freemarker -->
            <dependency>
                <groupId>freemarker</groupId>
                <artifactId>freemarker</artifactId>
                <version>2.3.9</version>
            </dependency>





 import lombok.Data;
    import java.util.List;
 
    /**
     * @description:
     * @author: sy0025
     * @create: 2019-09-06
     */
    @Data
    public class PdfParam {
    
        private String yearNumber;
  
        private String  symbol;
    
        private String subject;
        /**
         *发文对象
         */
        private String callName;
        /**
         *发文落款年
         */
        private String year;
        /**
         *发文落款月
         */
        private String month;
        /**
         *发文落款日
         */
        private String day;
    
        private List<TableVo> trs;
    
        private String internarSending;
    
    
        @Data
       public static class TableVo{
            private String employeeId;
    
            private String name;
    
            private String squence;
    
            private String squenceLevel;
        }
    
    }





 import com.china.ccd.oa.hrtransfer.model.bo.PdfParam;
    import com.itextpdf.text.BaseColor;
    import com.itextpdf.text.Document;
    import com.itextpdf.text.Font;
    import com.itextpdf.text.PageSize;
    import com.itextpdf.text.pdf.BaseFont;
    import com.itextpdf.text.pdf.PdfWriter;
    import com.itextpdf.tool.xml.XMLWorkerFontProvider;
    import com.itextpdf.tool.xml.XMLWorkerHelper;
    import freemarker.template.Configuration;
    import freemarker.template.DefaultObjectWrapper;
    import freemarker.template.Template;
    
    import java.io.BufferedWriter;
    import java.io.ByteArrayInputStream;
    import java.io.File;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.OutputStream;
    import java.io.PrintStream;
    import java.io.StringWriter;
    import java.nio.charset.Charset;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;

    public class PDFUtil {

    public static void main(String[] args) {
        PdfParam pdfParam  = new PdfParam();
        pdfParam.setYearNumber("2019");
        pdfParam.setSymbol("38");
        pdfParam.setSubject("XXXXX");
        pdfParam.setCallName("XXXXX");
        pdfParam.setYear("2019");
        pdfParam.setMonth("09");
        pdfParam.setDay("06");
        List<PdfParam.TableVo> tabs = new ArrayList<>();
        PdfParam.TableVo table = new PdfParam.TableVo();
        table.setEmployeeId("660579");
        table.setName("test");
        table.setSquence("通用序列-xxxxx");
        table.setSquenceLevel("高级四级");
        tabs.add(table);
        PdfParam.TableVo table2 = new PdfParam.TableVo();
        table2.setEmployeeId("660579");
        table2.setName("test");
        table2.setSquence("通用序列-xxxx");
        table2.setSquenceLevel("高级四级");
        tabs.add(table2);
        pdfParam.setTrs(tabs);
        pdfParam.setInternarSending("xxx会,xxx总经理室,xxx办公室,xxx人力资源部,xxx计划财务部,xxx监察保卫部,xxxx法律合规部。");
            PDFUtil pdfUtil = new PDFUtil();
            System.out.println(pdfUtil.createPdf(pdfParam));
     /*
        String name = buildHtml();
        PDFUtil pdfUtil = new PDFUtil("C:\\\\Users\\\\itw00100\\\\Desktop", name);

        PdfParam pdfParam  = new PdfParam();
        pdfParam.setYearNumber("2019");
        pdfParam.setSymbol("38");
        pdfParam.setSubject("XXXXX");
        pdfParam.setCallName("XXXXX");
        pdfParam.setYear("2019");
        pdfParam.setMonth("09");
        pdfParam.setDay("06");
        List tabs = new ArrayList<>();
        PdfParam.TableVo table = new PdfParam.TableVo();
        table.setEmployeeId("660579");
        table.setName("test");
        table.setSquence("通用序列-xxx");
        table.setSquenceLevel("高级四级");
        tabs.add(table);
        PdfParam.TableVo table2 = new PdfParam.TableVo();
        table2.setEmployeeId("660579");
        table2.setName("test");
        table2.setSquence("通用序列-xxxx");
        table2.setSquenceLevel("高级四级");
        tabs.add(table2);
        pdfParam.setTabs(tabs);

        System.out.println(pdfParam);


        Map paraMap = new HashMap();
        paraMap.put("yearNumber", pdfParam.getYearNumber());
        paraMap.put("symbol", pdfParam.getSymbol());
        paraMap.put("subject", pdfParam.getSubject());
        paraMap.put("callName", pdfParam.getCallName());
        paraMap.put("year", pdfParam.getYear());
        paraMap.put("month", pdfParam.getMonth());
        paraMap.put("day", pdfParam.getDay());
        List tableVoList = pdfParam.getTabs();
        StringBuffer sb = new StringBuffer();
        for(PdfParam.TableVo tableVo :tableVoList){
            sb.append("\n" +
                    "      \n" +
                    "         

"+tableVo.getEmployeeId()+"

\n" + " \n" + " \n" + "

"+tableVo.getName()+"

\n" + " \n" + " \n" + "

"+tableVo.getSquence()+"

\n" + " \n" + " \n" + "

"+tableVo.getSquenceLevel()+"

\n" + " \n" + " "); } paraMap.put("tabs", sb.toString()); try { String uploadfile = pdfUtil.fillTemplate(paraMap); System.out.println(uploadfile); } catch (Exception e) { e.printStackTrace(); } */
} /** * 生成pdf * @param pdfParam * @return */ public String createPdf(PdfParam pdfParam){ String tmpPath = "C:\\Users\\itw00100\\Desktop" + "\\temp"; File tmepFilePath = new File(tmpPath); if (!tmepFilePath.exists()) { tmepFilePath.mkdirs(); } String tmpFileName = System.currentTimeMillis() + ".pdf"; String outputFile = tmpPath + File.separatorChar + tmpFileName; FileOutputStream outFile = null; try { outFile = new FileOutputStream(outputFile); String itneralSendHtml = "







"
+ "







"
+ "








"
+ "








"
+ "
\n"
+ "

内部发送:"+pdfParam.getInternarSending()+"

\n"
+ "
"
; createPDFFile(buildHtml(pdfParam),itneralSendHtml, outFile); } catch (FileNotFoundException e) { e.printStackTrace(); }catch (Exception e){ e.printStackTrace(); } return outputFile; } /** * 直接构建html模板 * @param pdfParam * @return */ public String buildHtml(PdfParam pdfParam){ List<PdfParam.TableVo> tableVoList = pdfParam.getTrs(); StringBuffer trs = new StringBuffer(); for(PdfParam.TableVo tableVo :tableVoList){ trs.append("\n" + " \n" + "

"+tableVo.getEmployeeId()+"

\n"
+ " \n" + " \n" + "

"+tableVo.getName()+"

\n"
+ " \n" + " \n" + "

"+tableVo.getSquence()+"

\n"
+ " \n" + " \n" + "

"+tableVo.getSquenceLevel()+"

\n"
+ " \n" + " "); } StringBuffer htmlTemplete = new StringBuffer(); htmlTemplete.append("\n" + "\n" + "\n" + " \n" + " \n" + "\n" + "\n" + "

XXX

\n"
+ "

xxxxx中心 (XXX部)\n" + "

\n"
+ "
\n"
+ "

xxxx人部字〔"+pdfParam.getYearNumber()+"〕"+pdfParam.getSymbol()+"号

\n"
+ "
\n"
+ "

\n"
+ "

\n"
+ "

\n"
+ "

xxxx中心人力资源部

\n"
+ "

关于"+pdfParam.getSubject()+"人员序列聘任的通知

\n"
+ "

\n"
+ "

\n"
+ "

\n"
+ "

"+pdfParam.getCallName()+":

\n"
+ "

经研究决定:

\n"
+ "

"+pdfParam.getSubject()+"人员序列聘任结果如下:

\n"
+ "\n"+" \n"+" \n"+" \n"+" \n"+" \n"+" \n"+" \n"+""+trs.toString()+""+"\n"+"
\n" + "

员编

\n"
+ "
\n" + "

姓名

\n"
+ "
\n" + "

通道/序列

\n"
+ "
\n" + "

序列等级

\n"
+ "
\n"
+ "

XXX部

\n"
+ "

"+pdfParam.getYear()+"年"+pdfParam.getMonth()+"月"+pdfParam.getDay()+"日

\n"
+ "\n" + ""); return htmlTemplete.toString(); } /** * 构建framker模板 * @return */ public static String buildHtml() { StringBuffer htmlTemplete = new StringBuffer(); htmlTemplete.append("\n" + "\n" + "\n" + " \n" + " \n" + "\n" + "\n" + "

xxx

\n"
+ "<h1 style=\"text-align:center;font-weight: bold;font-family:方正小标宋简体\"> <span style=\"display:inline;font-size:21.3px;font-family:仿宋_GB2312\">(人力资源部)\n" + "\n" + "
\n"
+ "

XXX人部字〔${yearNumber}〕${symbol}号

\n"
+ "
\n"
+ "

\n"
+ "

\n"
+ "

\n"
+ "

xxxx人力资源部

\n"
+ "

关于${subject}人员序列聘任的通知

\n"
+ "

\n"
+ "

\n"
+ "

\n"
+ "

${callName}:

\n"
+ "

经研究决定:

\n"
+ "

${subject}人员序列聘任结果如下:

\n"
+ "\n"+" \n"+" \n"+" \n"+" \n"+" \n"+" \n"+" \n"+"${tabs}"+"\n"+"
\n" + "

员编

\n"
+ "
\n" + "

姓名

\n"
+ "
\n" + "

通道/序列

\n"
+ "
\n" + "

序列等级

\n"
+ "
\n"
+ "

xxx人力资源部

\n"
+ "

${year}年${month}月${day}日

\n"
+ "\n" + ""); String pdfTempleteName = "pdfTemplete.html"; PDFUtil pdfUtil = new PDFUtil("C:\\Users\\itw00100\\Desktop", "pdfTemplete.html"); pdfUtil.createdHtmlTemplate(htmlTemplete.toString()); return pdfTempleteName; } /* * 填充模板 * @param paramMap * @throws Exception */ public String fillTemplate(Map<String, Object> paramMap) throws Exception { File modelFile = new File(tempFilePath); if (!modelFile.exists()) { modelFile.mkdirs(); } Configuration configuration = new Configuration(); configuration.setDirectoryForTemplateLoading(modelFile); configuration.setObjectWrapper(new DefaultObjectWrapper()); configuration.setDefaultEncoding("UTF-8"); //获取或创建一个模版。 Template template = configuration.getTemplate(tempFileName); StringWriter stringWriter = new StringWriter(); BufferedWriter writer = new BufferedWriter(stringWriter); template.process(paramMap, writer); //把值写进模板 String htmlStr = stringWriter.toString(); writer.flush(); writer.close(); String tmpPath = tempFilePath + "/temp"; File tmepFilePath = new File(tmpPath); if (!tmepFilePath.exists()) { tmepFilePath.mkdirs(); } String tmpFileName = System.currentTimeMillis() + ".pdf"; String outputFile = tmpPath + File.separatorChar + tmpFileName; FileOutputStream outFile = new FileOutputStream(outputFile); createPDFFile(htmlStr,"", outFile); return outputFile; } /** * 根据HTML字符串创建PDF文件 * * @param htmlStr * @param os * @throws Exception */ private void createPDFFile(String htmlStr,String appendHtml, OutputStream os) throws Exception { ByteArrayInputStream bais = new ByteArrayInputStream(htmlStr.getBytes("UTF-8")); Document document = new Document(PageSize.A4); try { PdfWriter writer = PdfWriter.getInstance(document, os); PDFBuilder builder = new PDFBuilder(); writer.setPageEvent(builder); document.open(); FontProvider provider = new FontProvider(); XMLWorkerHelper.getInstance().parseXHtml(writer, document, bais, Charset.forName("UTF-8"), provider); //新起一页追加内容 document.newPage(); //document.add(new Paragraph("New page")); ByteArrayInputStream bais2 = new ByteArrayInputStream(appendHtml.getBytes("UTF-8")); XMLWorkerHelper.getInstance().parseXHtml(writer, document, bais2, Charset.forName("UTF-8"), provider); } catch (Exception e) { e.printStackTrace(); throw e; } finally { try { document.close(); } catch (Exception e) { e.printStackTrace(); } try { bais.close(); } catch (Exception e) { e.printStackTrace(); } } } /** * 字体 */ private class FontProvider extends XMLWorkerFontProvider { @Override public Font getFont(final String fontname, final String encoding, final boolean embedded, final float size, final int style, final BaseColor color) { BaseFont bf = null; try { if(fontname == null){ bf = BaseFont.createFont("/public/assets/fonts/" + "simhei" + ".ttf", BaseFont.IDENTITY_H , BaseFont.EMBEDDED); }else{ bf = BaseFont.createFont("/public/assets/fonts/" + fontname + ".ttf", BaseFont.IDENTITY_H , BaseFont.EMBEDDED); } } catch (Exception e) { e.printStackTrace(); } Font font = new Font(bf, size, style, color); font.setColor(color); return font; } } /** * 生成html模板 * * @param content * @return */ public String createdHtmlTemplate(String content) { String fileName = tempFilePath + "/" + tempFileName; try { File file = new File(tempFilePath); if (!file.isDirectory()) { file.mkdir(); } file = new File(fileName); if (!file.isFile()) { file.createNewFile(); } //打开文件 PrintStream printStream = new PrintStream(new FileOutputStream(fileName), true, "UTF-8"); //将HTML文件内容写入文件中 printStream.println(content); printStream.flush(); printStream.close(); System.out.println("生成html模板成功!"); } catch (Exception e) { e.printStackTrace(); } return fileName; } private String tempFilePath; private String tempFileName; public PDFUtil() { } public PDFUtil(String tempFilePath, String tempFileName) { this.tempFilePath = tempFilePath; this.tempFileName = tempFileName; } public String getTempFilePath() { return tempFilePath; } public void setTempFilePath(String tempFilePath) { this.tempFilePath = tempFilePath; } public String getTempFileName() { return tempFileName; } public void setTempFileName(String tempFileName) { this.tempFileName = tempFileName; } } import com.itextpdf.text.Document; import com.itextpdf.text.DocumentException; import com.itextpdf.text.Element; import com.itextpdf.text.Font; 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; /** * 设置页面附加属性 * */ public class PDFBuilder extends PdfPageEventHelper { /** * 页眉 */ public String header = ""; /** * 文档字体大小,页脚页眉最好和文本大小一致 */ public int presentFontSize = 12; /** * 文档页面大小,最好前面传入,否则默认为A4纸张 */ public Rectangle pageSize = PageSize.A4; // 模板 public PdfTemplate total; // 基础字体对象 public BaseFont bf = null; // 利用基础字体生成的字体对象,一般用于生成中文文字 public Font fontDetail = null; /** * * Creates a new instance of PdfReportM1HeaderFooter 无参构造方法. * */ public PDFBuilder() { } /** * * Creates a new instance of PdfReportM1HeaderFooter 构造方法. * * @param yeMei * 页眉字符串 * @param presentFontSize * 数据体字体大小 * @param pageSize * 页面文档大小,A4,A5,A6横转翻转等Rectangle对象 */ public PDFBuilder(String yeMei, int presentFontSize, Rectangle pageSize) { this.header = yeMei; this.presentFontSize = presentFontSize; this.pageSize = pageSize; } 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); } //加分页 public void addPage(PdfWriter writer, Document document){ try { if (bf == null) { bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", false); } if (fontDetail == null) { fontDetail = new Font(bf, presentFontSize, Font.NORMAL);// 数据体字体 } } catch (DocumentException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } // 1.写入页眉 ColumnText.showTextAligned(writer.getDirectContent(), Element.ALIGN_LEFT, new Phrase(header, fontDetail), document.left(), document.top() + 20, 0); // 2.写入前半部分的 第 X页/共 int pageS = writer.getPageNumber(); String foot1 = "第 " + pageS + " 页/共"; Phrase footer = new Phrase(foot1, fontDetail); // 3.计算前半部分的foot1的长度,后面好定位最后一部分的'Y页'这俩字的x轴坐标,字体长度也要计算进去 = len float len = bf.getWidthPoint(foot1, presentFontSize); // 4.拿到当前的PdfContentByte PdfContentByte cb = writer.getDirectContent(); // 5.写入页脚1,x轴就是(右margin+左margin + right() -left()- len)/2.0F // 再给偏移20F适合人类视觉感受,否则肉眼看上去就太偏左了 // ,y轴就是底边界-20,否则就贴边重叠到数据体里了就不是页脚了;注意Y轴是从下往上累加的,最上方的Top值是大于Bottom好几百开外的。 // ColumnText // .showTextAligned( // cb, // Element.ALIGN_CENTER, // footer, // (document.rightMargin() + document.right() // + document.leftMargin() - document.left() - len) / 2.0F + 20F, // document.bottom() - 20, 0); // 6.写入页脚2的模板(就是页脚的Y页这俩字)添加到文档中,计算模板的和Y轴,X=(右边界-左边界 - 前半部分的len值)/2.0F + // len , y 轴和之前的保持一致,底边界-20 // cb.addTemplate(total, (document.rightMargin() + document.right() // + document.leftMargin() - document.left()) / 2.0F + 20F, // document.bottom() - 20); // 调节模版显示的位置 // i % 2 == 0 ? "偶数" : "奇数"; if(pageS % 2 == 0){ ColumnText .showTextAligned( cb, Element.ALIGN_CENTER, footer, document.left()+25F , document.bottom() - 20, 0); // 6.写入页脚2的模板(就是页脚的Y页这俩字)添加到文档中,计算模板的和Y轴,X=(右边界-左边界 - 前半部分的len值)/2.0F + // len , y 轴和之前的保持一致,底边界-20 cb.addTemplate(total, document.left()+25F , document.bottom() - 20); // 调节模版显示的位置 }else{ ColumnText .showTextAligned( cb, Element.ALIGN_CENTER, footer, (document.rightMargin() + document.right() + document.leftMargin() - document.left() - len)-75F , document.bottom() - 20, 0); // 6.写入页脚2的模板(就是页脚的Y页这俩字)添加到文档中,计算模板的和Y轴,X=(右边界-左边界 - 前半部分的len值)/2.0F + // len , y 轴和之前的保持一致,底边界-20 cb.addTemplate(total, (document.rightMargin() + document.right() + document.leftMargin() - document.left())-75F, document.bottom() - 20); // 调节模版显示的位置 } } /** * * TODO 关闭文档时,替换模板,完成整个页眉页脚组件 * * @see PdfPageEventHelper#onCloseDocument(PdfWriter, * Document) */ public void onCloseDocument(PdfWriter writer, Document document) { // 7.最后一步了,就是关闭文档的时候,将模板替换成实际的 Y 值,至此,page x of y 制作完毕,完美兼容各种文档size。 total.beginText(); total.setFontAndSize(bf, presentFontSize);// 生成的模版的字体、颜色 String foot2 = " " + (writer.getPageNumber()) + " 页"; total.showText(foot2);// 模版显示的内容 total.endText(); total.closePath(); } }

注:可以定义多种字体,需下载.ttf文件

你可能感兴趣的:(技术)