简介
- 本文使用openpdf 1.3.29 版本,也建议使用openpdf。
<dependency> <groupId>com.github.librepdf</groupId> <artifactId>openpdf</artifactId> <version>1.3.29</version> </dependency>
- OpenPDF 是基于 itext4 开发的开源的jar,itext5也是基于 itext4 开发,且itext5是部分开源,部分收费,且官方不再更新维护,需要引入的包多,itext7绝大部分功能收费了
- OpenPDF相比 itext5简单使用,且在github下载源码,里面有些例子,共参考
- 有兴趣的可以下载看看:
https://github.com/LibrePDF/OpenPDF
软件安装
- 所需软件Adobe Acrobat XI Pro,用于制作PDF模板,也可下载其他版本,仅供参考
- 可去官网下载,有30天试用期,可使用amtemu.v0.9.2-painter激活,官网下载需要注册用户
https://www.adobe.com/cn/products/catalog.html
- 由于上传有存在版权问题,无法上传,需要可以留言联系
制作PDF模板
- 使用Adobe Acrobat XI Pro创建各种需要的域
- 条形码
使用选定的域对输入进行编码,并将它显示为可以通过解码软件或硬件(分别提供)来解释的可视模式。 - 按钮
促发用户计算机上的变化,如打开文件、播放声音,或者向网络服务器提交数据。这些按钮可通过图像、文本以及鼠标动作触发的可见变化进行自定义。 - 复选框
为个别项显示是或否选择。如果表单包含多个复选框,用户通常可以根据需要选择。 - 数字签名域
允许用户使用数字签名以电子形式对 PDF 文档进行签名。 - 下拉列表
允许用户从弹出式菜单中选择项,或键入值。您可以设置表单域属性,以使用户可以输入自定义值。 - 列表框
显示用户可以选择的选项列表。您可以设置表单域属性,以使用户可以按 Shift 键并单击来选择列表中的多个项。 - 单选钮
显示一组选项,用户仅可以从中选择一项。名称相同的所有单选钮作为一个组一起工作。 - 文本域
允许用户键入文本,例如名称、地址或电话号码。
- 条形码
- 步骤如下:
- 建议先创建一个word,先绘制出来想要的表格或文档(在Adobe Acrobat XI Pro中编辑PDF中不太方便话表格,同时操作内容没有word丰富),然后将word导出PDF,个人使用的是WPS
- 用Adobe Acrobat XI Pro 打开,点击编辑图标,右边展示了编辑框,注意内容和表单是常用,如下:
- 编辑或新增域,点击表单-编辑;定义域的一般属性 名称 是否可见 只读 ,字体大小
- 在代码中通过获取该名称属性来进行对模板填值
- 域的属性里,可设置字体,和多行,多行可自动换行,注意域的宽高不够时显示不出来
- 重要: 最好将域的字体设置为TIme New Roman,然后代码使用宋体,这样就能兼容中午,即:一段文字,英文显示TIme New Roman,中文显示宋体
代码
- 个人写了个工具类,
- 注意:由于STSong-Light与simsun字体不一样,使用浏览器打开字体有差异,需要导入simsun,simsun就是我们使用WPS,Adobe Acrobat XI Pro选择的宋体
package com.test.business.util;
import com.easipass.commoncore.exception.EasiServiceException;
import com.lowagie.text.pdf.*;
import lombok.extern.slf4j.Slf4j;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.List;
import java.util.Map;
/**
* 描述:创建PDF 工具类
* * @author bpzhang
* @date 2022/7/15 12:55
*/
@Slf4j
public class CreatePdfUtil {
private CreatePdfUtil() {
throw new IllegalStateException("Utility class");
}
/**
* 根据用Adobe Acrobat XI编辑好的PDF模板,生成pdf,放入输出流os,
*
* @param templateFilePath 模板路径,一般在resources下,直接文件名即可
* @param os 生成的pdf输出流,方便调用者自己管理,关闭流等
* @param fieldMapList 需要生成pdf域的填充值,List.size就是多少页
*/
public static void createPdfByTemplate(String templateFilePath, OutputStream os, List<Map<String, String>> fieldMapList) {
try (PdfReader reader = new PdfReader(templateFilePath)) {
PdfCopyFields copy = new PdfCopyFields(os);
fieldMapList.forEach(fieldMap -> {
try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
PdfStamper stamp = new PdfStamper(reader, bos);
AcroFields form = stamp.getAcroFields();
BaseFont bfChinese = BaseFont.createFont("fonts/simsun.ttc,0",BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED);
form.addSubstitutionFont(bfChinese);
fieldMap.forEach((key, value) -> {
try {
form.setField(key, value);
} catch (IOException e) {
log.error(e.getMessage(), e);
throw new EasiServiceException(e.getMessage());
}
});
stamp.setFormFlattening(true);
stamp.close();
PdfReader pdfReader = new PdfReader(bos.toByteArray());
pdfReader.close();
copy.addDocument(pdfReader);
} catch (IOException e) {
log.error(e.getMessage(), e);
throw new EasiServiceException(e.getMessage());
}
});
copy.close();
} catch (IOException e) {
log.error(e.getMessage(), e);
throw new EasiServiceException(e.getMessage());
}
}
}
- 两种调用方式;templateFilePath=模板路径, os = 生成的pdf输出流,可以给目录加文件名outputPath,直接生成文件,或者自动保存到OS流中,自行处理,fieldMapList=key:域的名字,value:域值
- ** 重点** 域中在value使用\n可换行
CreatePdfUtil.createPdfByTemplate("pdftmpl/EDS_DECL.pdf", os, fieldMapList);
CreatePdfUtil.createPdfByTemplate("pdftmpl/EDS_DECL.pdf", Files.newOutputStream(Paths.get(outputPath)), fieldMapList);
余留问题:
- 域中如果中英文同时存在,空格自动换行
- 域中行间距调节不了
解决方案:
- 问题一:可计算域的一行可放多少个字符,然后代码在固定的字符中增加\n换行符
- 问题二:暂时无解方案,只能调节字体大小
以上内容,问题有更好解决方案,欢迎评论区讨论
转载,或者引用请注明出处,已经看到要几个网站直接原原本本贴过去,过分了!