admin管理员组文章数量:1649185
前端页面
效果图
实现思路
- 需要前端录入一部分数据
- 框架使用:itext+FreeMarker ,layui前端框架+ssm框架
- 前端POST提交数据后以 json字符串存入数据库表A中CLOB类型的content字段中
- POST提交后回调函数按表A中对应数据ID查找数据生成PDF并直接下载
POM.XML引入依赖
<!-- freemarker engine -->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>${freemarker.version}</version>
</dependency>
<dependency>
<groupId>com.lowagie</groupId>
<artifactId>itext</artifactId>
<version>2.1.7</version>
<exclusions>
<exclusion>
<artifactId>bcmail-jdk14</artifactId>
<groupId>bouncycastle</groupId>
</exclusion>
<exclusion>
<artifactId>bcprov-jdk14</artifactId>
<groupId>bouncycastle</groupId>
</exclusion>
<exclusion>
<artifactId>bctsp-jdk14</artifactId>
<groupId>bouncycastle</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.xhtmlrenderer</groupId>
<artifactId>flying-saucer-pdf</artifactId>
<version>9.0.3</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.4.5</version>
</dependency>
<dependency>
<groupId>com.itextpdf.tool</groupId>
<artifactId>xmlworker</artifactId>
<version>5.4.5</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
前端JS代码
说明:前端对象为Person,可以添加删除行的那部分数据使用ArrayList对象为PrintData,Person中对应了一条账单Bill的ID
function submitPrint(){
//非空校验
if(!$("#inputForm").valid()){return false;}
//获取表单数据(对象)
var data = $("#inputForm").serialize();
//POST异步请求提交数据储存到数据库
axios({
method: 'post',
url: "${ctx}/xxx/xxxXXXxxx/submitPrintData", //此方法下方列出
data: $("#inputForm").serialize()
}).then(function (data) {
//浏览器返回的响应码
var status = data.status;
//response数据中的msg值对应的数据(是表A中此条需要被打印数据的id)
var contentId = data.data.msg;
if(status =='200'){//正常
layer.alert("保存成功,下载中...",{// 保存成功
closeBtn:0,
btn:["确定"],
yes:function(index){
var contentId = data.data.msg;
layer.close(index);
//生成PDF文件(根据id找到数据,输出)
window.location.href="${ctx}/xxx/xxxXXXxxx/print?contentId="+contentId; //此方法下方列出
}
})
}else{
layer.alert("失败",
{title:'提示',btn:'确认'});//保存失败
}
}).catch(function (error) {
layer.alert("失败",
{title:'提示',btn:'确认'});//保存失败
});
}
后端储存数据代码
@ResponseBody
@RequestMapping(value = "submitPrintData",method=RequestMethod.POST)
public Map<String,String> submitPrintData(Person person,
Model model,HttpServletRequest request, HttpServletResponse response ){
//返回前端的消息集合创建
HashMap<String,String> mapForResult = new HashMap<>();
//什么什么条件是存储数据失败的,返回给前端
if(....) {
mapForResult.put("status", "400");
return mapForResult;
}
//删除以前A表中打印的数据(为了留存痕迹,只是标记删除,没有物理删除)
AService.deleteByBillId(billId);
//创建A表新对象
A a = new A();
//创建需要存进A表中的数据的容器,使用map,
Map<String, Object> map=new HashMap<>();
//把map装满数据
map.put("date", ...);
map.put("noStr", ...);
...
//把装满数据map变成json串存进数据库表A
JSONObject joForContent = new JSONObject(map);
a.setRepContents(joForContent.toJSONString());
aService.save(a);
String contentId = a.getId();
mapForResult.put("msg", contentId);//前端通过此id获取数据后取出数据进行打印
mapForResult.put("status", "200");
return mapForResult;
}
后端print代码
@RequestMapping(value = "print")
public void print(Model model,HttpServletRequest request, HttpServletResponse response )
throws Exception {
//获取想打印数据id
String contentId = request.getParameter("contentId");
//查询数据
A a = aService.get(contentId);
//查出数据转为map
Map<String,Object> map = (Map<String,Object>)JSONObject.parseObject(a.getRepContents());
/** 开始生成PDF方法*/
//设置编码
response.setCharacterEncoding("UTF-8");
//设置生成的PDF文件名
response.setHeader("Content-Disposition","attachment;filename=" +
URLEncoder.encode("武林协会收费清单.pdf","UTF-8"));
//freemarker去指定路径寻找画好的模板,带着数据去模板上,(此处模板枚举对应的)
String html=freemarkerService.getHtml(
PdfEnum.武林协会收费清单.getName(),map); //此方法在下方
//工具类,把带有数据的模板传到前端生成文件
PdfUtils.createPdf(response, html); //此方法在下方
}
freemarkerService代码
@Component //(把普通pojo实例化到spring容器中,相当于配置文件中的<bean id="" class=""/>)
public class FreemarkerService {
@Autowired
private Configuration configuration; //package freemarker.template;freemarker.template包里的类
public String getHtml(String fileName,Map<String,Object> map) throws Exception {
//指定模板所在位置
String freemarkerPath="templates\\xxxxxx\\freemarkexxxxxxxxx\\";
//springd加载资源文件的ClassPathResource方法
Resource resource = new ClassPathResource(freemarkerPath);
//java.io.File:getAbsoluteFile是不会抛出异常的,返回:绝对路径名字符串,此处为后面模板中引入图片做准备
map.put("basePath", resource.getFile().getAbsoluteFile());
//按名字获取到模板
Template template = configuration.getTemplate(fileName);
//执行 写
StringWriter writer = new StringWriter();
template.process(map,writer);
writer.flush();
writer.close();
String html=writer.toString();
writer.close();
//写成一个“页面”
return html;
}
}
PdfUtils工具类
public class PdfUtils {
public static void createPdfForBsDebitNote(HttpServletResponse response,String html) throws Exception{
//创建文件
Document doc = new Document(PageSize.A4,0,0,0,0);
//输出流:资源到前端一个文件的过程
OutputStream stream = response.getOutputStream();
//package com.itextpdf.text.pdf; 添加到此文档的内容将被写入outputstream.
PdfWriter pdfWriter = PdfWriter.getInstance(doc,stream);
pdfWriter.setPageEvent(new PdfPageEventHelper(){
@Override
public void onEndPage(PdfWriter writer, Document document) {
PdfContentByte cb = writer.getDirectContent();
try{
cb.setFontAndSize(BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED),6);
} catch (com.itextpdf.text.DocumentException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
cb.saveState();
cb.beginText();
cb.endText();
cb.restoreState();
}
});
doc.setMargins(10, 10, 10, 10);
doc.open();
//以下可以使用itextpdf带有的丰富的方法去写,去画,但我们使用并做好了模板,因此把模板搞成字节输入流取代那些方法
ByteArrayInputStream byteArrayInputStream=new ByteArrayInputStream(html.getBytes());
//这种将XHTML/CSS或XML流解析为PDF的是被itextpdf接收的并且itextpdf提供了帮助类XMLWorkerHelper,使用后直接搞定
XMLWorkerHelper.getInstance().parseXHtml(pdfWriter,doc,byteArrayInputStream);
doc.close();
stream.close();
}
}
模板(使用的ftl类型文件:网页模板和数据模型的结合体)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3/1999/xhtml">
<head>
<title>武林协会收费清单模板</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style type="text/css">
body {
font-family: Microsoft YaHei;
}
@page {
size: A4;
}
</style>
</head>
<!-- 白底黑字 -->
<body bgcolor="#FFFFFF" leftmargin="0" topmargin="0" marginwidth="0" marginheight="0">
<!-- 最上方的留白 -->
<table style="width: 100%; border-collapse: collapse;">
<tr>
<td style="width: 100%;height:22px;"><strong> </strong></td>
</tr>
</table>
<!-- LOGO和标题 -->
<table style="width: 100%; border-collapse: collapse;">
<tr>
<!-- 第一列为LOGO -->
<td style="width:25%;height:155px">
<table>
<tr>
<!-- freemarkerPath那写好的路径 LOGO文件路径,使用的gif类型的文件 -->
<td><img src="${basePath}/logo.gif" width="181" height="155"/></td>
</tr>
</table>
</td>
<!-- 第二列为题目,题目又分很多行 -->
<td style="width:75%;height:155px">
<table>
<tr><td style="height:18%"> </td></tr>
<tr><td style="height:18%;font-size:15px;text-align:center;"><strong>武林协会</strong></td></tr>
<tr><td style="height:16%;font-size:13px;text-align:center;"><strong>北京市丰台区。。。</strong></td></tr>
<tr><td style="height:18%"></td></tr>
</table>
</td>
</tr>
</table>
<!-- 文字 -->
<table style="width: 100%; border-collapse: collapse;">
<tr>
<td style="width: 100%;height:35px;font-size:20px;text-align:center;"><strong>收款通知单</strong></td>
</tr>
</table>
<!-- 文字(这个地方写的不是很好)以下内容在一个大大大table里 -->
<table style="width: 100%; border-collapse: collapse; font-size: 12px;">
<tr>
<td style="width: 100%; height: 150px;">
<table>
<tr>
<td style="height: 150px;" >
<table>
<tr>
<td style="width: 25%;padding-left: 60px; float: right;font-size: 12px;">${who?if_exists}</td>
<td style="width: 20%"></td>
<td style="width: 25%;padding-left: 60px; float:right;font-size: 12px;">NO。。</td>
</tr>
<tr>
<td style="height: 30%"></td>
</tr>
<tr>
<td style="width: 25%;padding-left: 60px; float: right;font-size: 12px;">${..?if_exists}</td>
<td style="width: 20%"></td>
<td style="width: 25%;padding-left: 60px; float:right;font-size: 12px;">Date..</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
<!-- 那条横线 -->
<tr>
<td><img src="${basePath}/topLine.gif" width="754" height="2px" /></td>
</tr>
<!-- 页面上录的那些文字 -->
<tr>
<td style="width: 580px; height: 400px;padding-left: 20px">
<table style="font-size: 12px;padding-left: 20px">
<tr>
<td style="width: 12%;padding-left: 60px; float: left">${zeroName?if_exists}</td>
<td style="width: 55%;float: left">${zeroContent?if_exists}</td>
<td style="width: 35%;"></td>
</tr>
<tr>
<td style="width: 12%;padding-left: 60px; float: left">${oneName?if_exists}</td>
<td style="width: 55%;float: left">${oneContent?if_exists}</td>
<td style="width: 35%;"></td>
</tr>
...
<tr>
<td style="height: 20%"></td>
</tr>
</table>
<table style="font-size: 12px;padding-left: 20px">
<tr><td style="padding-left: 60px; float: left">DUR AND PAYABLE</td></tr>
<tr>
<td style="padding-left: 60px; float: left">--------------------------------------------------------</td>
</tr>
<tr><td style="padding-left: 60px; float: left">Date :${Date?if_exists}</td></tr>
</table>
</td>
<!-- 右侧那条竖线 -->
<td><img src="${basePath}/rightLine.gif" width="2" height="435px" /></td>
<!-- 右侧那条数据 -->
<td style="width: 290px; height: 435px;" colspan='1'>
<table>
<tr>
<td colspan="3" style="padding-left: 30px;font-size: 12px;">${currency?if_exists} ${amount?if_exists}</td>
</tr>
</table>
</td>
</tr>
<!-- 下方那条横线 -->
<tr>
<td><img src="${basePath}/Line.gif" width="754px" height="2px" /></td>
</tr>
<!-- 横线下方的字 -->
<tr>
<td style="width:600px;">
<table style="font-size: 11px;padding-left: 20px">
<tr style="padding-left: 60px; float: left; ">
<td style="padding-left: 60px; float: left;font-size: 10px; ">xxxxxxxxxx</td>
</tr>
</table>
</td>
</tr>
<!-- 大大大表格结束 -->
</table>
</body>
</html>
本文标签: 后端文件数据FreemarkerJava
版权声明:本文标题:java(itextpdf+FreeMarker)生成PDF文件(带logo)从前端post提交数据到后端 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://m.elefans.com/xitong/1729504633a1203484.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论