业务中遇到在pdf文件上盖章,添加文字信息(签名)的需求:包含单图片,多图片,多参数方法
老样子,直接上代码和注释,使用的方法类
引入jar包依赖
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13<dependency> <groupId>com.itextpdf</groupId> <artifactId>itextpdf</artifactId> <version>5.5.6</version> </dependency> <!-- itextpdf的亚洲字体支持 --> <dependency> <groupId>com.itextpdf</groupId> <artifactId>itext-asian</artifactId> <version>5.2.0</version> </dependency>
controller层代码:
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54@PostMapping("/print") @ApiOperation(value = "打印结果") public ResponseMessage print(@RequestBody PrintResultRequest request) { OrganPrintSignature reviewer = null; OrganPrintSignature verifier = null; //这里是指定输出为流文件对象给前端,前端拿来使用“预览和下载”行为 HttpServletResponse response = HttpContextUtil.getHttpServletResponse(); try { OutputStream os = response.getOutputStream(); // 设定输出文件头 response.setHeader( "Content-disposition", "attachment; filename=" + new String(("打印结果结果.pdf") .getBytes("GB2312"), "ISO8859-1")); // 定义输出类型 response.setContentType("application/pdf"); //签名url的map集合 key:用来做枚举,获取指定类型的url在pdf上的位置 HashMap<String, String> imgMap = new HashMap<>(); //pdfUrl:一般pdf都是把通用模板上传到服务器,引用的是服务器绝对路径 InputStream docIn = new FileInputStream(new File(pdfUrl)); log.info("------------- 文件读取成功,准备写入pdf"); //审核签名url if (ObjectUtil.isNotNull(reviewer)) { imgMap.put("examineImg", reviewer.getUrl()); } //本人签名url if (ObjectUtil.isNotNull(verifier)) { imgMap.put("checkImg", verifier.getUrl()); } //印章图片url if (ObjectUtil.isNotNull(organPrintConfig.getSignetUrl())) { imgMap.put("sealImg", organPrintConfig.getSignetUrl()); } //输出时间格式化 DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); //需要印在pdf文件上的文本参数 参数根据业务获取,这里举两个例子 Map<String, String> map = new HashMap<>(); map.put("name", "奥特曼"); map.put("nowTime", df.format(LocalDateTime.now())); //填充pdf文件 os.write(PDFUtil.signs(map, docIn, imgMap, 0, 1)); log.info("------------- 填充pdf文件完成"); } catch (Exception e) { String result = "系统提示:下载失败,原因:" + e.toString(); log.error(result, e); throw new ServiceException(ResultCode.SYSTEM_BUSY); } return ResponseMessage.ok(); }
pdfUtil方法类:
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258@Slf4j @Configuration public class PDFUtil { /** * 读取pdf中文字信息(全部) */ public static void READPDF(String inputFile) { //创建文档对象 PDDocument doc = null; String content = ""; PdfDomainDTO vo = new PdfDomainDTO(); try { //加载一个pdf对象 doc = PDDocument.load(new File(inputFile)); //获取一个PDFTextStripper文本剥离对象 PDFTextStripper textStripper = new PDFTextStripper(); content = textStripper.getText(doc); //vo.setContent(content); System.out.println("内容:" + content); System.out.println("全部页数" + doc.getNumberOfPages()); //关闭文档 doc.close(); } catch (Exception e) { // TODO: handle exception } } /** * 将一张图片添加到PDF文件上,类似签名 * * @param docInput PDF文件 * @param imgInput 图片文件,建议是无背景的PNG格式文件 * @param x 以左下角为原点的x坐标 * @param y 左下角为原点的y坐标 * @param imgHeight 带有签名文字的图片宽度 * @param imgWidth 带有签名文字的图片高度 * @param rotation 带有签名文字的图片的旋转角度,逆时针旋转,如果不旋转则为0 * @param pageNum 需要签名的页码数组,从1开始 * @return 返回签好名的PDF文件字节码 */ public static byte[] addImgToDoc(Map<String, String> map, InputStream docInput, InputStream imgInput, int x, int y, float imgWidth, float imgHeight, float rotation, int[] pageNum) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { PdfReader reader = new PdfReader(docInput); PdfStamper stamp = new PdfStamper(reader, baos); stamp.setRotateContents(false); //印章图片 byte[] imgBytes = new byte[imgInput.available()]; IOUtils.read(imgInput, imgBytes); Image img = Image.getInstance(imgBytes); img.scaleAbsoluteWidth(imgWidth); img.scaleAbsoluteHeight(imgHeight); img.setAbsolutePosition(x, y); //这个字体是itext-asian.jar中自带的 所以不用考虑操作系统环境问题. BaseFont bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED); //baseFont不支持字体样式设定.但是font字体要求操作系统支持此字体会带来移植问题. Font font = new Font(bf, 30); font.setStyle(Font.NORMAL); font.getBaseFont(); for (int pn : pageNum) { img.setRotationDegrees(rotation + reader.getPageRotation(pn)); // 旋转角度 PdfContentByte over = stamp.getOverContent(pn); over.addImage(img); //开始写入文本 over.beginText(); //设置字体和大小 over.setFontAndSize(font.getBaseFont(), 10); //设置字体颜色 //over.setColorFill(new BaseColor(0,110,107,100)); com.itextpdf.text.pdf.PdfGState gState = new PdfGState(); gState.setStrokeOpacity(0.1f); over.setGState(gState); for (Map.Entry<String, String> entry : map.entrySet()) { PdfAxisEnum anEnum = PdfAxisEnum.fetch(entry.getKey()); //要输出的text(对齐方式,写的字,设置字体的输出位置,字体是否旋转) if (ObjectUtil.isNotNull(anEnum)) { over.showTextAligned(0, entry.getValue(), anEnum.getXAxis(), anEnum.getYAxis(), 0); if (anEnum.getParam().equals("result")) { over.showTextAligned(0, entry.getValue(), anEnum.getXAxis() + 140, anEnum.getYAxis(), 0); } } } over.endText(); } stamp.close(); reader.close(); } catch (Exception e) { e.printStackTrace(); } return baos.toByteArray(); } /** * 将多张图片添加到PDF文件上,类似签名 * * @param map 要写入的文本map * @param docInput PDF文件 * @param imgMap 要添加的图片,输入流 * @param rotation 带有签名文字的图片的旋转角度,逆时针旋转,如果不旋转则为0 * @param pageNum 需要签名的页码数组,从1开始 * @return 返回签好名的PDF文件字节码 */ public static byte[] addImgsToDoc(Map<String, String> map, InputStream docInput, Map<String, String> imgMap, float rotation, int[] pageNum) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { PdfReader reader = new PdfReader(docInput); PdfStamper stamp = new PdfStamper(reader, baos); stamp.setRotateContents(false); //这个字体是itext-asian.jar中自带的 所以不用考虑操作系统环境问题. BaseFont bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED); //baseFont不支持字体样式设定.但是font字体要求操作系统支持此字体会带来移植问题. Font font = new Font(bf, 30); font.setStyle(Font.NORMAL); font.getBaseFont(); for (int pn : pageNum) { PdfContentByte over = stamp.getOverContent(pn); //循环写入图片,并按照枚举菜单取出在pdf中对应的位置 for (Map.Entry<String, String> entry : imgMap.entrySet()) { log.info("------------- 开始写入图片"); // byte[] imgBytes = new byte[entry.getValue().available()]; // IOUtils.read(entry.getValue(), imgBytes); Image img = Image.getInstance(entry.getValue()); PdfAxisEnum anEnum = PdfAxisEnum.fetch(entry.getKey()); //要添加的图片 if (ObjectUtil.isNotNull(anEnum)) { //图片大小 int imgWidth = 0; int imgHeight = 0; if (anEnum.getParam().equals("sealImg")) { //印章图片 imgWidth = 100; imgHeight = 100; } else if (anEnum.getParam().equals("checkImg") || anEnum.getParam().equals("examineImg")) { //签名图片1 imgWidth = 40; imgHeight = 20; } img.scaleAbsoluteWidth(imgWidth); img.scaleAbsoluteHeight(imgHeight); img.setAbsolutePosition(anEnum.getXAxis(), anEnum.getYAxis()); img.setRotationDegrees(rotation + reader.getPageRotation(pn)); // 旋转角度 over.addImage(img); } } log.info("------------- 开始写入文本"); //开始写入文本 over.beginText(); //设置字体和大小 over.setFontAndSize(font.getBaseFont(), 10); //设置字体颜色 //over.setColorFill(new BaseColor(0,110,107,100)); com.itextpdf.text.pdf.PdfGState gState = new PdfGState(); gState.setStrokeOpacity(0.1f); over.setGState(gState); for (Map.Entry<String, String> entry : map.entrySet()) { PdfAxisEnum anEnum = PdfAxisEnum.fetch(entry.getKey()); //要输出的text(对齐方式,写的字,设置字体的输出位置,字体是否旋转) if (ObjectUtil.isNotNull(anEnum)) { if (StrUtil.isNotEmpty(entry.getValue())) { over.showTextAligned(0, entry.getValue(), anEnum.getXAxis(), anEnum.getYAxis(), 0); } if (anEnum.getParam().equals("result")) { over.showTextAligned(0, entry.getValue(), anEnum.getXAxis() + 140, anEnum.getYAxis(), 0); } } } over.endText(); } stamp.close(); reader.close(); } catch (Exception e) { log.error("写入pdf文件失败", e); } return baos.toByteArray(); } /** * 将一张图片添加到PDF文件上,类似签名 * * @param doc PDF文件 * @param img 图片文件,建议是无背景的PNG格式文件 * @param x 以左下角为原点的x坐标 * @param y 左下角为原点的y坐标 * @param imgHeight 带有签名文字的图片宽度 * @param imgWidth 带有签名文字的图片高度 * @param rotation 带有签名文字的图片的旋转角度,逆时针旋转,如果不旋转则为0 * @param pageNum 需要签名的页码数组,从1开始 * @return 返回签好名的PDF文件字节码 */ public static byte[] sign(Map<String, String> map, InputStream doc, InputStream img, int x, int y, float imgWidth, float imgHeight, float rotation, int... pageNum) { if (pageNum == null || pageNum.length == 0) { return null; } return addImgToDoc(map, doc, img, x, y, imgWidth, imgHeight, rotation, pageNum); } /** * 将多张图片添加到PDF文件上,类似签名 * * @param map 要写入的文本map集合 * @param doc PDF文件 * @param imgMap 要添加的图片,输入流集合 * @param rotation 带有签名文字的图片的旋转角度,逆时针旋转,如果不旋转则为0 * @param pageNum 需要签名的页码数组,从1开始 * @return 返回签好名的PDF文件字节码 */ public static byte[] signs(Map<String, String> map, InputStream doc, Map<String, String> imgMap, float rotation, int... pageNum) { if (pageNum == null || pageNum.length == 0) { return null; } return addImgsToDoc(map, doc, imgMap, rotation, pageNum); } /** * 根据url保存到指定路径 * * @param url url地址 * @param saveAddress 文件新路径 */ public static void downloadFile(String url, String saveAddress) { try { URL fileUrl = new URL(url); InputStream is = fileUrl.openStream(); OutputStream os = new FileOutputStream(saveAddress); byte bf[] = new byte[1024]; int length = 0; while ((length = is.read(bf, 0, 1024)) != -1) { os.write(bf, 0, length); } is.close(); os.close(); } catch (Exception e) { log.error(e.toString()); } } }
枚举菜单PdfAxisEnum类代码:
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50@Getter public enum PdfAxisEnum { /** * 姓名 */ NAME("name", 60, 625), /** * 时间 */ NOW_TIME("nowTime", 80, 562), /** * 签名图片 */ CHECK_IMG("checkImg", 425, 400), /** * 签名图片 */ EXAMINE_IMG("examineImg", 520, 400), /** * 印章图片 */ SEAL_IMG("sealImg", 460, 700), ; /** * 参数名 */ public String param; /** * x轴数值 */ public Integer xAxis; /** * y轴数值 */ public Integer yAxis; PdfAxisEnum(String param, Integer xAxis, Integer yAxis) { this.param = param; this.xAxis = xAxis; this.yAxis = yAxis; } public static PdfAxisEnum fetch(String param) { for (PdfAxisEnum value : PdfAxisEnum.values()) { if (value.param.equals(param)) { return value; } } return null; } }
最后
以上就是贪玩抽屉最近收集整理的关于pdf文件添加文字/图片,“签名”功能,方法工具类的全部内容,更多相关pdf文件添加文字/图片内容请搜索靠谱客的其他文章。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复