admin管理员组文章数量:1592311
文章目录
- (一)需求描述
- (二)制作模板
- (三)代码开发
(一)需求描述
构建PDF模板,对其中部分数据实现动态插入,主要分为三个组件:普通文本,复选框,二维码图片的动态插入
(二)制作模板
因为PDF常用的软件不让支持编辑,我们就先使用WPS以Word的形式进行编辑制作出与客户需求一样的样式,然后直接另存为 .pdf 的形式如下图所示:
构建完PDF之后,我们需要使用Adobe Acrobat DC的软件来编辑文本域,软件下载不在赘述
用Adobe Acrobat DC打开该测试PDF,点击准备表单,下面介绍下该软件的基本使用,其中序号1处为构建的值域,可以自定义拖曳修改,序号2可以添加一些自定义的组件,比如文本,单选框,按钮等等,序号3展示当前PDF的域对象
配置数据源域名称,这个就是后面动态插入值匹配的属性,图片插入可以直接使用文本组件,只要域名匹配即可
复选框单独说明一下,我在开发中发现网络上存在多种说法对于复选框的选择,其实这个都是不明确的,具体是设置On,是,Yes或者其他的都是可以的,而且PDF的默认值也不一样,这个需要在Adobe Acrobat DC特别编辑下,在选项中可以设置样式,其中导出值就是后面你在代码里选择的On,当给对应域值设置On即表示确认选择,这个需要特别注意下,不然出现无法选择问题找不到解决办法
(三)代码开发
导入依赖,itextpdf是主要的编辑PDF依赖,itext-asian是亚洲字体的依赖
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.13</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
PDF操作代码
public static byte[] createSimplePdf(Map<String, Map<String, String>> dataMap, String templatePath) {
PdfReader reader;
ByteArrayOutputStream bos;
PdfStamper stamper;
ByteArrayOutputStream out = null;
try {
//获取文件流
reader = new PdfReader(templatePath);
bos = new ByteArrayOutputStream();
stamper = new PdfStamper(reader, bos);
AcroFields form = stamper.getAcroFields();
//遍历设值
for (Map.Entry<String, Map<String, String>> data : dataMap.entrySet()) {
String fieldType = data.getKey();
if ("simple".equals(fieldType)) {
for (Map.Entry<String, String> dataValue : data.getValue().entrySet()) {
//支持中文
BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
form.setFieldProperty(data.getKey(), "textfont", bfChinese, null);
//saveAppearance需要设置为true,
form.setField(dataValue.getKey(), dataValue.getValue(), true);
}
} else if ("image".equals(fieldType)) {
//处理图片类型域
for (Map.Entry<String, String> dataValue : data.getValue().entrySet()) {
int pageNo = form.getFieldPositions(dataValue.getKey()).get(0).page;
Rectangle signRect = form.getFieldPositions(dataValue.getKey()).get(0).position;
float x = signRect.getLeft();
float y = signRect.getBottom();
// 读图片
Image image = PngImage.getImage(dataValue.getValue());
// 获取操作的页面
PdfContentByte under = stamper.getOverContent(pageNo);
// 根据域的大小缩放图片
image.scaleToFit(signRect.getWidth(), signRect.getHeight());
// 添加图片
image.setAbsolutePosition(x, y);
under.addImage(image);
stamper.setFormFlattening(true);
}
}
}
//不可编辑
stamper.setFormFlattening(true);
out = new ByteArrayOutputStream();
Document doc = new Document();
PdfCopy copy = new PdfCopy(doc, out);
stamper.close();
doc.open();
PdfImportedPage importPage = copy.getImportedPage(new PdfReader(bos.toByteArray()), 1);
copy.addPage(importPage);
doc.close();
out.close();
} catch (IOException | DocumentException e) {
e.printStackTrace();
}
assert out != null;
return out.toByteArray();
}
测试代码
public static void main(String[] args) throws IOException {
Map<String, Map<String, String>> dataSet = new HashMap<>(3);
String imgPath = "D:\\img.png";
Map<String, String> map1 = new HashMap<>(2);
map1.put("name", "Hello World");
map1.put("flag", "On");
Map<String, String> map2 = new HashMap<>(2);
map2.put("img", imgPath);
dataSet.put("simple", map1);
dataSet.put("image", map2);
byte[] simplePdf = PdfUtil.createSimplePdf(dataSet, "D:\\test.pdf");
File file = new File("target.pdf");
FileOutputStream fileOutputStream = new FileOutputStream(file);
fileOutputStream.write(simplePdf);
fileOutputStream.close();
}
生成的PDF结果
说明:
1:上面为了方便直接用了Map操作的,建议实际开发替换为实体类代替
2:目前只碰到了文本、复选框,图片类型,其中文本复选框操作一样,图片稍有不同
3:复选框操作的时候必须设置saveAppearance需要设置为true否则不会生效
版权声明:本文标题:Java实现PDF动态插入图片复选框 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://www.elefans.com/dianzi/1728139187a1147140.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论