有人私信我说看了上篇文章,但是不知道怎么创建pdf模板,而且有一些代码不明白。更了那么久博客总算有人私信问我问题/(ㄒoㄒ)/~~,正好今天又做这个功能所以更一篇文章详细讲述从使用Adobe Acrobat DC创建模板,到生成pdf文件以及对一些数据的处理操作。
古人云:工欲善其事必先利其器,所以小弟特地给大佬们备好Adobe Acrobat DC软件压缩包,自取哦。百度网盘链接 提取码:b8ow
有些时候我们收到的并不是pdf文件,而是客户发过来的.jpg或者png图片,这时候就需要我们将文件先转为pdf文件。
右击打开我们要转换的文件
执行保存操作,保存的就是pdf文件。(Ctrl+s)
其实上一步我们不保存也可以,创建模板完毕后再保存。下面的页面右击pdf文件,选择编辑操作如果pdf模板没有创建打开的页面和直接打开图片文件是一样的。
① 点击准备表单
② 点击开始,其实上两步也可以不这么操作,不过感觉这么方便,点击开始那儿也可以选择文件,下面是创建表单的页面。。。。红色圈出来的就是你要动态渲染的值,当然这是因为我打开的是已经更改的,毕竟为了写博客我也要自己先走一遍流程。
③ 添加文本域
点击文本按钮,然后在你想动态改变的位置添加,然后在域名称输入你的参数名,如果是必选项可以在必选项打勾。
这时候就有小伙伴问了,如果俺文本太长放不下可咋整。( •̀ ω •́ )✧
下面最最最重要的来了,通过双击文本域,或者点击所有属性操作,切换到选项栏目卡,然后选中多行
如果是编辑好文本域的模板打开会提示:
那些灰色的就是你添加的文本域,可以选择编辑表单域然后修改。
将你所需的文本域都添加好然后保存,模板就做好啦。。。下面才是重头戏
<dependency>
<groupId>com.itextpdfgroupId>
<artifactId>itextpdfartifactId>
<version>5.5.13version>
dependency>
<dependency>
<groupId>com.itextpdfgroupId>
<artifactId>itext-asianartifactId>
<version>5.2.0version>
dependency>
俺也为你们准备了所需要的jar包,找了好久才找到。。。。。点击下载CSDN资源 不需要积分哦
咱身为一个程序员即使技术菜,但咱也要有写出优雅代码的心。首先创建一个pdfUtils.java工具类,这样以后可以复用,下面我贴上我的工具类代码,并且对每个我认为重要的地方加上注释,另外字体是宋体,至于使用其他的字体可以动动小手百度一下,面向百度编程嘛,不寒碜。
Controller里面调用生成pdf方法。
// 保存路径 生成
String savePath =GlConfig.getDownloadResourcePath() + "student/worksSafetyknowledgeCertificate/" + student.getName()+"WorksSafetyknowledgeCertificate.pdf";
PdfUtil.exportCertificateTemplateByPdf(savePath, info.toJson(), qrCodePath,1);
这是实体类中加的将对象转为json格式的方法:
public JSONObject toJson() {
return JSONUtil.parseObj(this);
}
pdf工具类中方法:
/**
* 生成安全生产知识和管理能力考核证书
*/
public static final URL SpecialAnquanshengchan = ResourceUtil.getResource("template/anquanshengchan.pdf");
/**
* pdf生成
*/
public static void exportCertificateTemplateByPdf(String savePath, JSONObject obj, String qrCodePath,int type) {
PdfReader reader = null;
ByteArrayOutputStream bos = null;
PdfStamper stamper = null;
OutputStream os = null;
FileOutputStream out = null;
File file;
Document document = null;
PdfCopy copy = null;
Document doc = null;
try {
/** 实例化文档对象 */
document = new Document(PageSize.A4, 50, 40, 40, 50);
/** 创建 PdfWriter 对象 */
// 打开文档
document.open();
/** pdf文档中中文字体的设置,注意一定要添加iTextAsian.jar包 */
String localFontPath = "c:\\windows\\fonts\\";
BaseFont bfChinese =
BaseFont.createFont(localFontPath + "simhei.ttf", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
// 这里是删除以前上传的附件 毕竟为了节省空间
FileUtils.deleteFile(savePath);
file = new File(savePath);
// 如果文件夹不存在 创建文件夹
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
out = new FileOutputStream(file);
// 根据type判断获取不同的模板
if (type == 0) {
reader = new PdfReader(SpecialOperationCertificate);
} else {
reader = new PdfReader(SpecialAnquanshengchan);
}
bos = new ByteArrayOutputStream();
stamper = new PdfStamper(reader, bos);
AcroFields form = stamper.getAcroFields();
// 文字类的内容处理
form.addSubstitutionFont(bfChinese);
String vlaues;
for (Map.Entry<String, Object> entry : obj.entrySet()) {
vlaues = String.valueOf(entry.getValue());
// 判断是否插入图片 如果不需要可以删除不用
if ("picname".equals(entry.getKey())) {
try {
// 通过域名获取所在页和坐标,左下角为起点
int pageNo = form.getFieldPositions(entry.getKey()).get(0).page;
Rectangle signRect = form.getFieldPositions(entry.getKey()).get(0).position;
// qrCode位置
Rectangle qrcode_signRect = form.getFieldPositions("qrcode").get(0).position;
float x = signRect.getLeft();
float y = signRect.getBottom();
// qrcode坐标位置
float qrcode_x = qrcode_signRect.getLeft();
float qrcode_y = qrcode_signRect.getBottom();
// 读图片
Image image = Image.getInstance(vlaues);
Image qrcode_image = Image.getInstance(qrCodePath);
// 获取操作的页面
PdfContentByte under = stamper.getOverContent(pageNo);
// 根据域的大小缩放图片
image.scaleToFit(signRect.getWidth(), signRect.getHeight());
qrcode_image.scaleToFit(qrcode_signRect.getWidth(), qrcode_signRect.getHeight());
// 添加图片
image.setAbsolutePosition(x, y);
qrcode_image.setAbsolutePosition(qrcode_x, qrcode_y);
under.addImage(image);
under.addImage(qrcode_image);
} catch (Exception e) {
log.info(e.getMessage());
}
} else {
// 对文本的处理
if ("fileCoding".equals(entry.getKey())) {
// 设置文本的大小 有的标题字体会比较大
form.setFieldProperty(entry.getKey(), "textsize", 55f, null);
} else {
form.setFieldProperty(entry.getKey(), "textsize", 20f, null);
}
form.setField(entry.getKey(), vlaues);
}
}
// 如果为false,生成的PDF文件可以编辑,如果为true,生成的PDF文件不可以编辑
stamper.setFormFlattening(true);
stamper.close();
doc = new Document();
copy = new PdfCopy(doc, out);
doc.open();
PdfImportedPage importPage = copy.getImportedPage(new PdfReader(bos.toByteArray()), 1);
copy.addPage(importPage);
doc.close();
document.close();
copy.flush();
copy.close();
} catch (Exception e) {
log.info(e.getMessage());
} finally {
try {
if (stamper != null) {
stamper.close();
stamper = null;
}
if (reader != null) {
reader.close();
reader = null;
}
IOUtils.closeQuietly(os);
IOUtils.closeQuietly(bos);
IOUtils.closeQuietly(out);
if (document != null) {
document.close();
document = null;
}
if (doc != null) {
doc.close();
doc = null;
}
if (copy != null) {
copy.flush();
copy.close();
copy = null;
}
} catch (Exception ignored) {
}
}
}
看在俺那么认真、详细整理的份上,如果对你有帮助麻烦点个赞,谢谢。看着访问量一点点的涨感觉很上瘾,本来就打算记录自己在项目中遇到的问题,以后需要的话可以直接查看,也没想着运营一下,一是因为如果只是为了访问量去复制别人的代码,自己连用都没用过就贴上去,有点。。。咱还是要脸的,二呢,咱技术水平也不咋的高,咳。因为俺也是面向百度编程,不会的也是需要找资料,但是在找的过程中发现好多有问题的也贴上去,一个功能不同博客代码都一摸一样,然后找着找着也不能用,很烦躁也浪费时间,我能做的就是对得起点开我博客文章的小伙伴,可能我水平不怎么高,但是我更的博客都是我在项目中、或者学习中使用到的内容,嘿嘿嘿。。。。