发布时间:2023-04-03 13:30
首先明白写字板签名完输出的是base64的图片,剩下的就是将此图片插入到pdf文件中,实现此步骤的技术很多,可以用itex5但是为了实现与其他数据一起动态插入我选择的freemark。
大概就是:签字版签名图片———》将图片插入ftl模板生成html文件—————》将html文件转成pdf(使用技术是wkhtmltopdf)
freemark:http://freemarker.foofun.cn/
FreeMarker 是一款 模板引擎: 即一种基于模板和要改变的数据, 并用来生成输出文本(HTML网页,电子邮件,配置文件,源代码等)的通用工具。 它不是面向最终用户的,而是一个Java类库,是一款程序员可以嵌入他们所开发产品的组件。
wkhtmltopdf:https://wkhtmltopdf.org/
khtmltoimage
是开源 (LGPLv3) 命令行工具,可使用 Qt WebKit 渲染引擎将 HTML 渲染为 PDF 和各种图像格式。这些完全“无头”运行,不需要显示或显示服务。
前面有此驱动的具体用法
上代码
依赖
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-freemarkerartifactId>
<version>2.1.10.RELEASEversion>
dependency>
1.对html模板改造
使用${}进行动态数据插入
2.编写控制层
freemarker默认是map集合传参方式键值对
键为${}中的pic,值为你需要插入的图片地址可以为虚拟路径
入参的数据源如果需要插入的字段不一样
3.ftl插入数据生成html工具类
/**
* freemarker配置 可以读取我们在yml中的配置,比如模版文件的路径,
*/
@Autowired
private FreeMarkerConfigurer freeMarkerConfigurer;
@Value("${file.root.path}")
private String rootPath;
/**
* 通过JSON生成Html,Excel,Word
*
* @param data 数据源
* @param fileName 文件名
* @param templateFilePath 模板文件路径
* @param templateFile 模板
*/
public static void createDayReportFiles(Map<String, Object> data, String fileName, String templateFilePath, String templateFile) {
BufferedInputStream in = null;
Writer out = null;
Template template = null;
try {
//构造Configuration
Configuration configuration = new Configuration();
configuration.setDefaultEncoding("utf-8");
configuration.setObjectWrapper(ObjectWrapper.BEANS_WRAPPER);
configuration.setDirectoryForTemplateLoading(new File(templateFilePath));
try {
//test.ftl为要装载的模板
template = configuration.getTemplate(templateFile);
} catch (IOException e) {
e.printStackTrace();
}
//输出文档路径及名称
File outFile = new File(fileName);
FileOutputStream fos = null;
try {
fos = new FileOutputStream(outFile);
OutputStreamWriter oWriter = new OutputStreamWriter(fos, "UTF-8");
//这个地方对流的编码不可或缺,使用main()单独调用时,应该可以,但是如果是web请求导出时导出后word文档就会打不开,并且包XML文件错误。主要是编码格式不正确,无法解析。
out = new BufferedWriter(oWriter);
} catch (FileNotFoundException e1) {
e1.printStackTrace();
}
//生成HTML
template.process(data, out);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (TemplateException e) {
e.printStackTrace();
} finally {
if (null != in) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (null != out) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
4.html文件转pdf工具类
有了带数据的html文件剩下的就是将此html文件转成pdf就行了
/**
* html转pdf
* @param srcPath html路径,可以是硬盘上的路径,也可以是网络路径
* @param destPath pdf保存路径
* @return 转换成功返回true
*/
public static boolean convert(String srcPath, String destPath){
File file = new File(destPath);
File parent = file.getParentFile();
//如果pdf保存路径不存在,则创建路径
if(!parent.exists()){
parent.mkdirs();
}
StringBuilder cmd = new StringBuilder();
cmd.append(toPdfTool);
cmd.append(" ");
cmd.append(" --header-line");//页眉下面的线
cmd.append(" --header-center 这里是页眉这里是页眉这里是页眉这里是页眉 ");//页眉中间内容
//cmd.append(" --margin-top 30mm ");//设置页面上边距 (default 10mm)
cmd.append(" --header-spacing 10 ");// (设置页眉和内容的距离,默认0)
cmd.append(srcPath);
cmd.append(" ");
cmd.append(destPath);
boolean result = true;
try{
//执行拼接后的命令
Process proc = Runtime.getRuntime().exec(cmd.toString());
HtmlToPdfInterceptor error = new HtmlToPdfInterceptor(proc.getErrorStream());
HtmlToPdfInterceptor output = new HtmlToPdfInterceptor(proc.getInputStream());
error.start();
output.start();
proc.waitFor();
}catch(Exception e){
result = false;
e.printStackTrace();
}
return result;
}
到此完美结束,核心代码就这么多,剩下的就是与你业务逻辑匹配就行,比如文件命名,保存位置,插入的数据。
有更好的方案欢迎与我一起讨论多多指教
5.效果图
完蛋图片传不上来