zoukankan      html  css  js  c++  java
  • Java之生成条形码、PDF、HTML

    关于Java生成HTML,可参考我的这篇文章:FreeMarker之根据模型生成HTML代码

    当然了,该篇文章也会给你很多启发,比如,根据html生成html,大家不要小看这个,著名的WordPress博客文章,本质上就是这个机制,每发表一篇文章相当于新生成的一个HTML,内容不一样,样式基本是一致的。

    下面进入正题:

    一、导入Maven依赖

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <groupId>com.foresee</groupId>
        <artifactId>mypdf</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <dependencies>
            <dependency>
                <groupId>com.itextpdf</groupId>
                <artifactId>itext-asian</artifactId>
                <version>5.2.0</version>
            </dependency>
            <dependency>
                <groupId>com.itextpdf</groupId>
                <artifactId>itextpdf</artifactId>
                <version>5.4.2</version>
            </dependency>
            <dependency>
                <groupId>org.xhtmlrenderer</groupId>
                <artifactId>core-renderer</artifactId>
                <version>R8</version>
            </dependency>
            <dependency>
                <groupId>org.freemarker</groupId>
                <artifactId>freemarker</artifactId>
                <version>2.3.23</version>
            </dependency>
    
            <dependency>
                <groupId>net.sf.barcode4j</groupId>
                <artifactId>barcode4j-light</artifactId>
                <version>2.0</version>
            </dependency>
    
        </dependencies>
    </project>

    二、编写Java代码

    package com.beck.util;
    
    import java.awt.image.BufferedImage;
    import java.io.ByteArrayOutputStream;
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.OutputStream;
    import org.krysalis.barcode4j.HumanReadablePlacement;
    import org.krysalis.barcode4j.impl.code39.Code39Bean;
    import org.krysalis.barcode4j.output.bitmap.BitmapCanvasProvider;
    import org.krysalis.barcode4j.tools.UnitConv;
    import sun.misc.BASE64Encoder;
    
    public class BarcodeUtil {
        
        public static final String IMG_TYPE_PNG="image/png";
        
        public static final String IMG_TYPE_GIF="image/gif";
        
        public static final String IMG_TYPE_JPEG="image/jpeg";
        
        public static String generateToBase64(String msg,String imgType) throws IOException {
            ByteArrayOutputStream ous = new ByteArrayOutputStream();
            generateToStream(msg,imgType, ous);
            BASE64Encoder encoder = new BASE64Encoder();
            return encoder.encode(ous.toByteArray());
        }
    
        public static File generateToFile(String msg,String imgType, File file)
                throws IOException {
            FileOutputStream out = new FileOutputStream(file);
            try {
                generateToStream(msg,imgType, out);
            } finally {
                if (out != null) {
                    out.close();
                }
            }
            return file;
        }
    
        public static byte[] generateToByte(String msg,String imgType) throws IOException {
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            try {
                generateToStream(msg,imgType, out);
                return out.toByteArray();
            } finally {
                if (out != null) {
                    out.close();
                }
            }
        }
    
        public static void generateToStream(String msg, String imgType,OutputStream out)
                throws IOException {
            if (msg == null || out == null) {
                return;
            }
            Code39Bean bean = new Code39Bean();
            // 精细度
            int dpi = 150;
            // module宽度
            double moduleWidth = UnitConv.in2mm(1.0f / dpi);
            bean.setModuleWidth(moduleWidth);
            // 不显示文字
            bean.setMsgPosition(HumanReadablePlacement.HRP_NONE);
            bean.setHeight(5);
            bean.setWideFactor(3);
            bean.doQuietZone(false);
        
            // 输出到流
            BitmapCanvasProvider canvas = new BitmapCanvasProvider(out, imgType,
                    dpi, BufferedImage.TYPE_BYTE_BINARY, false, 0);
            // 生成条形码
            bean.generateBarcode(canvas, msg);
            // 结束绘制
            canvas.finish();
        }
    
    
    }
    package com.beck.util;
    
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.OutputStreamWriter;
    import java.io.StringWriter;
    import java.io.Writer;
    import java.util.HashMap;
    import java.util.Locale;
    import java.util.Map;
    
    import freemarker.template.Configuration;
    import freemarker.template.Template;
    
    public class FreemarkerTemplate {
    
        private final Configuration configuration = new Configuration(
                Configuration.VERSION_2_3_23);
        private String charset;
    
        public FreemarkerTemplate(String charset) {
            this.charset = charset;
            configuration.setEncoding(Locale.CHINA, charset);
            configuration.setClassicCompatible(true);//处理空值为空字符串  
        }
    
        public void setTemplateClassPath(Class resourceLoaderClass,
                String basePackagePath) {
            configuration.setClassForTemplateLoading(resourceLoaderClass,
                    basePackagePath);
        }
    
        public void setTemplateDirectoryPath(String templatePath)
                throws IOException {
            configuration.setDirectoryForTemplateLoading(new File(templatePath));
        }
    
        public void processToStream(String templateFileName,
                Map<String, Object> dataMap, Writer writer) throws Throwable {
            Template template = configuration.getTemplate(templateFileName);
            template.process(dataMap, writer);
        }
    
        public void processToFile(String templateFileName,
                Map<String, Object> dataMap, File outFile) throws Throwable {
            Writer writer = new OutputStreamWriter(new FileOutputStream(outFile),
                    charset);
            try {
                processToStream(templateFileName, dataMap, writer);
            } catch (Throwable e) {
                e.printStackTrace();
            } finally {
                if (writer != null) {
                    writer.close();
                }
            }
        }
    
        public String processToString(String templateFileName,
                Map<String, Object> dataMap) throws Throwable {
            Writer writer = new StringWriter(2048);
            try {
                processToStream(templateFileName, dataMap, writer);
                return writer.toString();
            } finally {
                if (writer != null) {
                    writer.close();
                }
            }
        }
    
    
    }
    package com.beck.util;
    
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.OutputStream;
    
    import org.xhtmlrenderer.pdf.ITextFontResolver;
    import org.xhtmlrenderer.pdf.ITextRenderer;
    
    import com.itextpdf.text.pdf.BaseFont;
    
    public class PDFUtils {
        private static String fontBasePath=PDFUtils.class.getResource("/").getPath()+"font/";
        public static void htmlFileToPDFStream(File htmlFile, OutputStream output,
                File imageBaseURL) throws Throwable {
            if (htmlFile == null) {
                throw new RuntimeException("htmlFile is null");
            }
            if (output == null) {
                throw new RuntimeException("output is null");
            }
    
            // 生成ITextRenderer实例
            ITextRenderer renderer = new ITextRenderer();
            // 关联html页面
            renderer.setDocument(htmlFile.toURI().toURL().toString());
            // 设置获取图片的基本路径
            renderer.getSharedContext().setBaseURL(
                    imageBaseURL.toURI().toURL().toString());
            // 设置字体路径,必须和html设置一致
            ITextFontResolver fontResolver = renderer.getFontResolver();
            
            
            fontResolver.addFont(fontBasePath+"msyh.ttc", BaseFont.IDENTITY_H,
                    BaseFont.NOT_EMBEDDED);
            fontResolver.addFont(fontBasePath+"msyhl.ttc", BaseFont.IDENTITY_H,
                    BaseFont.NOT_EMBEDDED);
            fontResolver.addFont(fontBasePath+"msyhbd.ttc", BaseFont.IDENTITY_H,
                    BaseFont.NOT_EMBEDDED);
            renderer.layout();
            renderer.createPDF(output);
        }
    
        public static void htmlFileToPDFFile(File htmlFile, File pdfFile,
                File imageBaseURL) throws Throwable {
            OutputStream output = new FileOutputStream(pdfFile);
            try {
                htmlFileToPDFStream(htmlFile, output, imageBaseURL);
            } finally {
                if (output != null) {
                    output.close();
                }
            }
        }
    
    }
    package com.beck.util;
    
    public class Receipt {
        private String receiptType;
        private double amount;
        public String getReceiptType() {
            return receiptType;
        }
        public void setReceiptType(String receiptType) {
            this.receiptType = receiptType;
        }
        public double getAmount() {
            return amount;
        }
        public void setAmount(double amount) {
            this.amount = amount;
        }
    }

    三、在src/main/resources建立HTML页面和相关的文件夹

    建立font、images、templates文件夹

    文件夹如图所示:

    html代码:

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    
    <title>报销单</title>
    <style type="text/css" rel="stylesheet">
    * {
        margin: 0;
        padding: 0;
    }
    body {
        font-family: "Microsoft YaHei UI";
        font-size: 12px;
        max- 555px;
        margin: 0 auto;
        padding: 20px;
    }
    h1 {
        text-align: center;
        font-size: 18px;
        color: #000;
        font-weight: bold;
    }
    .comptitle {
        height: 66px;
    }
    .comptitle h2 {
        float: left;
        height: 66px;
        line-height: 66px;
        font-size: 14px;
        color: #000;
        font-weight: bold;
    }
    .barcode {
         162px;
        float: right;
        padding: 10px 0;
        text-align: center;
    }
    .barcode img {
         162px;
        height: 30px;
        display: table-cell;
        vertical-align: middle;
        margin-bottom: 5px;
    }
    .barcode h3 {
        font-size: 12px;
        color: #000;
    }
    .stafftbl, .detailstbl, .approverrd {
        border-collapse: collapse;
        border: 1px solid #f3f3f3;
    }
    .stafftbl th, .stafftbl td, .detailstbl th, .detailstbl td, .approverrd th, .approverrd td {
        height: 20px;
        line-height: 20px;
        border: 1px solid #f3f3f3;
    }
    .stafftbl th {
        font-weight: normal;
        background: #f8f9fd;
        text-align: right;
        color: #777;
        padding-right: 12px;
    }
    .stafftbl td {
        padding-left: 10px;
    }
    .wrap p {
        color: #000;
        margin: 12px 0 10px;
    }
    .detailstbl th, .approverrd th {
        font-weight: normal;
        color: #777;
        background: #f8f9fd;
        border: none;
    }
    .detailstbl td, .approverrd td {
        text-align: center;
    }
    .sum {
        background: #f8f9fd;
        color: #777;
    }
    .detailstbl td.sumdata {
        text-align: right;
        padding-right: 20px;
        font-weight: bold;
    }
    </style>
    </head>
    
    <body>
    <div class="wrap">
      <h1>费用报销单</h1>
      <div class="comptitle">
        <h2>*****有限公司</h2>
        <div class="barcode"><img src="${barcodeImg}" alt=""></img>
           <h3>${barcode}</h3>
        </div>
      </div>
      <table width="100%" border="0" cellspacing="0" cellpadding="0" class="stafftbl">
        <tbody>
          <tr>
            <th width="18%">报销人</th>
            <td width="32%">${userName}</td>
            <th width="18%">填写日期</th>
            <td>${submitDate}</td>
          </tr>
          <tr>
            <th>费用所属部门</th>
            <td colspan="3">${deptName}</td>
          </tr>
          <tr>
            <th>所属项目</th>
            <td colspan="3">运营平台2.0</td>
          </tr>
          <tr>
            <th>报销事由</th>
            <td colspan="3">${reimReason}</td>
          </tr>
        </tbody>
      </table>
      <p>费用明细</p>
      <table width="100%" border="0" cellspacing="0" cellpadding="0" class="detailstbl">
        <tbody>
          <tr>
           
            <th width="8%">序号</th>
            <th>发票类型</th>
            <th width="10%">发票张数</th>
            <th width="12%">发票金额</th>
            <th width="12%">报销金额</th>
            <th>专票税额</th>
            <th width="28%">用途</th>
          </tr>
          <#list receiptList as item>
          <tr>
            <td >${list_index+1}</td>
            <td>${item.receiptType}</td>
            <td>1</td>
            <td>¥${item.amount}</td>
            <td>¥${item.amount}</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
          </tr>
          </#list>
          <tr>
            <td colspan="2" class="sum">总报销金额(小写)</td>
            <td colspan="5" class="sumdata" >¥259.46</td>
          </tr>
          <tr>
            <td colspan="2" class="sum">总报销金额(大写)</td>
            <td colspan="5" class="sumdata" >贰佰伍拾玖元肆角陆分</td>
          </tr>
        </tbody>
      </table>
      <p>审批记录</p>
      <table width="100%" border="0" cellspacing="0" cellpadding="0" class="approverrd">
        <tbody>
          <tr>
            <th width="8%">序号</th>
            <th>节点名称</th>
            <th>电子签名</th>
            <th>签名日期</th>
            <th width="8%">操作</th>
            <th width="25%">备注</th>
          </tr>
          <tr>
            <td>1</td>
            <td>提交</td>
            <td>张三/平台支撑部</td>
            <td>2018-09-18  16:18:41</td>
            <td>提交</td>
            <td>&nbsp;</td>
          </tr>
        </tbody>
      </table>
    </div>
    </body>
    </html>

     图片要求必须符合png、jpg等格式,只要是这些格式的都行。

    四、编写测试类

    package com.beck.util;
    
    import java.io.File;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    import java.util.UUID;
    
    public class Test {
    
        public static void main(String[] args) throws Throwable {
             
            String barcode = "12345678910";
            String uuid=UUID.randomUUID().toString();
            String htmlBasePath="E://Demo//workspace//mypdf//src//main//resources//template";//html的根目录
            String tempathBasePath=Test.class.getResource("/").getPath()+"template/";//模板路径
            String pdfBasePath="E://Demo//workspace//mypdf//src//main//resources//template";//生成的pdf目录
            
            String barCodePath="E://Demo//workspace//mypdf//src//main//resources//images//"+uuid+".png";
            String htmlPath=htmlBasePath+uuid+".html";
            String pdfPath=pdfBasePath+uuid+".pdf";
            
            //生成条形码
            File barCodeFile=new File(barCodePath);
            BarcodeUtil.generateToFile(barcode,BarcodeUtil.IMG_TYPE_PNG,barCodeFile);
            System.out.println("生成条形码完成!");
            //生成html
            FreemarkerTemplate tp=new FreemarkerTemplate("UTF-8");
            tp.setTemplateDirectoryPath(tempathBasePath);
            //封装数据 start ,必须是Map
            Map<String, Object> dataMap = new HashMap<String, Object>();
            dataMap.put("barcode",barcode);
            dataMap.put("barcodeImg",barCodePath);
            dataMap.put("userName", "游总");
            dataMap.put("submitDate", "2018-09-18");
            dataMap.put("deptName", "研发平台");
            //费用明细
            List<Receipt> receiptList=new ArrayList<Receipt>();//Receipt 必须是public类型的类
            Receipt r1=new Receipt();
            r1.setReceiptType("普通发票");
            r1.setAmount(100);
            
            Receipt r2=new Receipt();
            r2.setReceiptType("普通发票");
            r2.setAmount(100);
            
            receiptList.add(r1);
            receiptList.add(r2);
            
            dataMap.put("receiptList", receiptList);
            //封装数据 end
            File htmlFile=new File(htmlPath);
            tp.processToFile("expense.html", dataMap,htmlFile);
            System.out.println("生成html完成!");
            //生成pdf
            PDFUtils.htmlFileToPDFFile(htmlFile, new File(pdfPath), new File(htmlBasePath));
            System.out.println("生成pdf完成!");
            
    
        }
    
    }

    运行结果如图所示(控制台打印这些就表示没有问题,如果控制台报错,常见错误就是文件找不到异常,改下路径就可以了,一般情况是没有其他错误):

    pdf显示如图:

    html显示如图:

    条形码显示如图:

    源码地址:https://github.com/youcong1996/study_simple_demo.git

    如果实在上述代码,不能运行,大家可以将源码移植过来,运行效果是没有问题的。

  • 相关阅读:
    myfocus官方网站已经挂掉,相关下载已经从googlecode转到网盘
    [综合]visio2013安装提示找不到Office.zh_cnofficeMUI.mis officemui.xml
    技巧分享:解决Word 2010当中“分页符”造成的空白行
    房贷计算器代码2.0
    房贷计算器代码
    图解-JS普通函数跟箭头函数中this的指向问题
    完全基于net core容器的超级轻量化的Quartz,支持类似net core mvc的过滤器,附过滤器实现源码
    net下的高性能轻量化半自动orm+linq的《SqlBatis》
    轻量级ORM《sqlcommon》第一个版本发布了!!!
    从0开始编写dapper核心功能、压榨性能、自己动手丰衣足食
  • 原文地址:https://www.cnblogs.com/youcong/p/9671098.html
Copyright © 2011-2022 走看看