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-width: 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 {
    width: 162px;
    float: right;
    padding: 10px 0;
    text-align: center;
}
.barcode img {
    width: 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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值