前端页面
效果图
实现思路
- 需要前端录入一部分数据
- 框架使用: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();
axios({
method: 'post',
url: "${ctx}/xxx/xxxXXXxxx/submitPrintData",
data: $("#inputForm").serialize()
}).then(function (data) {
var status = data.status;
var contentId = data.data.msg;
if(status =='200'){
layer.alert("保存成功,下载中...",{
closeBtn:0,
btn:["确定"],
yes:function(index){
var contentId = data.data.msg;
layer.close(index);
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;
}
AService.deleteByBillId(billId);
A a = new A();
Map<String, Object> map=new HashMap<>();
map.put("date", ...);
map.put("noStr", ...);
...
JSONObject joForContent = new JSONObject(map);
a.setRepContents(joForContent.toJSONString());
aService.save(a);
String contentId = a.getId();
mapForResult.put("msg", contentId);
mapForResult.put("status", "200");
return mapForResult;
}
后端print代码
@RequestMapping(value = "print")
public void print(Model model,HttpServletRequest request, HttpServletResponse response )
throws Exception {
String contentId = request.getParameter("contentId");
A a = aService.get(contentId);
Map<String,Object> map = (Map<String,Object>)JSONObject.parseObject(a.getRepContents());
response.setCharacterEncoding("UTF-8");
response.setHeader("Content-Disposition","attachment;filename=" +
URLEncoder.encode("武林协会收费清单.pdf","UTF-8"));
String html=freemarkerService.getHtml(
PdfEnum.武林协会收费清单.getName(),map);
PdfUtils.createPdf(response, html);
}
freemarkerService代码
@Component
public class FreemarkerService {
@Autowired
private Configuration configuration;
public String getHtml(String fileName,Map<String,Object> map) throws Exception {
String freemarkerPath="templates\\xxxxxx\\freemarkexxxxxxxxx\\";
Resource resource = new ClassPathResource(freemarkerPath);
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();
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();
ByteArrayInputStream byteArrayInputStream=new ByteArrayInputStream(html.getBytes());
XMLWorkerHelper.getInstance().parseXHtml(pdfWriter,doc,byteArrayInputStream);
doc.close();
stream.close();
}
}
模板(使用的ftl类型文件:网页模板和数据模型的结合体)
<!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>
<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>
<table style="width: 100%; border-collapse: collapse;">
<tr>
<td style="width:25%;height:155px">
<table>
<tr>
<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 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>