您的位置:首页 > 编程语言 > Java开发

Java之生成条形码、PDF、HTML

2018-09-18 20:49 691 查看

关于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

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

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: