使用注意点
因为原来制作的pdf表单内容过于复杂,下面代码只包含前两行的操作。
本次操作需要前端向后端发起请求,后端返回数据给前端用于下载,所以没有在本地进行保存。
第 1 步制作pdf模板需要的pdf编辑软件基本上都需要钱,可以去买一个
第 2 步获取的pdf导出的中文需要的文件,如果pdf输出的内容有中文就需要去弄一下这个文件,在代码中用于读取设置中文字体
保函内容
1、导出pdf
2、设置斜体水印
pdf_12">1、制作pdf模板
先将需要的pdf模板通过word制作出来,然后导出为pdf
pdf" />
使用Adobe Acrobat DC 打开并制作模板(其他pdf编辑软件也可以)
选择打开前面导出的pdf模板
点击准备表单
点击之后,可以针对没一个位置进行编辑,选中双击就可以进行编辑了,要注意,每个位置的名字都需要是唯一的
全部赋值后保存即可
pdf_24">2、获取pdf导出中文需要的文件
获取中文字体需要的文件
在电脑这个路径下选择下载一个就行
3、实现
controller接口
java"> @GetMapping("/exportPDF/{applyId}")public ResponseEntity<byte[]> exportPDF(@PathVariable("applyId") String applyId, HttpServletResponse response) throws IOException,ParseException,Exception {byte[] res = applyService.exportPDF(applyId);HttpHeaders headers = new HttpHeaders();headers.add("Content-Disposition", "attachment; filename=filled_form.pdf");headers.add("Content-Type", "application/pdf");return ResponseEntity.ok().headers(headers).body(res);}
service具体实现
java"> public static byte[] exportPDF1() throws Exception {String inputTemplateName = "template";try {pdfBytes = null;Map<String, String> map = new HashMap<>();SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");// map预填数据,用于后面读取输出到pdf文件上map.put("department-1", "研发中心");map.put("submitDate-1", sdf.format(new Date()));map.put("submitPerson-1", "张三");map.put("travelPerson-1", "李四");map.put("receivePerson-1","王五");// 设置中文字体PdfFont chineseFont = PdfFontFactory.createFont("src/main/resources/file/simsun.ttc,0");// 模板路径String templatePath = "src\\main\\resources\\file\\" + inputTemplateName + ".pdf";// 重点,这一个关联了reader 和 writerByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();// 读取文件FileInputStream pdfInputStream = new FileInputStream(new File(templatePath));// 定义 reader 和writerPdfReader reader = new PdfReader(pdfInputStream);PdfWriter writer = new PdfWriter(byteArrayOutputStream,new WriterProperties().setStandardEncryption(null,null,EncryptionConstants.ALLOW_PRINTING, // 允许打印EncryptionConstants.ENCRYPTION_AES_128 // 加密方式));// 根据 reader 和writer 创建 PdfDocumentPdfDocument pdfDocument = new PdfDocument(reader,writer);// 下面是给文件添加水印,不需要的可以直接删掉// 获取 pdf 模板页数int numberOfPages = pdfDocument.getNumberOfPages();// 遍历每一页并添加水印for (int i = 1; i <= numberOfPages; i++) {PdfPage page = pdfDocument.getPage(i);// 获取页面尺寸(在这里我没有用)int pageWidth = (int) Math.floor(page.getPageSize().getWidth());int pageHeight = (int) Math.floor(page.getPageSize().getHeight());// 创建一个 PdfCanvas 对象PdfCanvas canvas = new PdfCanvas(page);// 保存当前坐标系状态canvas.saveState();// 水印内容旋转double angle = Math.toRadians(45);double cos = Math.cos(angle);double sin = Math.sin(angle);canvas.concatMatrix(cos, sin, -sin, cos, 0, 0);// 设置水印的字体和透明度canvas.setFontAndSize(PdfFontFactory.createFont(), 20);canvas.setFillColorRgb(0.75f, 0.75f, 0.75f); // 灰色canvas.setLineWidth(2);// 正常应该根据获取到的页面尺寸进行 x y 轴的遍历并// 但是我这边没有铺满,就自己设置了遍历的范围for (int x = -90; x < 2000; x += 300) {for (int y = -190; y < 2000; y += 200) {// 绘制水印文字canvas.beginText();canvas.setTextMatrix(x, y); // 设置水印位置canvas.showText("Watermark Text this is just a test"); // 水印文字内容canvas.endText();}}// 恢复坐标系状态canvas.restoreState();}// form 可以理解为把pdf文件看做一个form表单,以key value键值对保存PdfAcroForm form = PdfAcroForm.getAcroForm(pdfDocument, true);// 遍历上面预填的 map 并将值根据 key 赋值到formfor (Map.Entry<String, String> entry : map.entrySet()) {form.getField(entry.getKey()).setValue(entry.getValue());form.getField(entry.getKey()).setFont(chineseFont).setFontSize(8);}pdfDocument.close();// 返回文件流pdfBytes = byteArrayOutputStream.toByteArray();return pdfBytes;} catch (Exception e) {e.printStackTrace();}finally {return pdfBytes;}}
4、前端发起请求并生成下载链接
exportPdf(applyId) {exportPDF(applyId).then(res => {// 创建一个 Blob 对象,指定类型为 PDF 文件const blob = new Blob([res.data], { type: 'application/pdf' });// 创建一个 URL 对象,指向 Blob 数据const url = URL.createObjectURL(blob);// 创建一个下载链接const link = document.createElement('a');link.href = url;link.download = 'generated_with_form.pdf'; // 设置下载文件名// 模拟点击下载链接link.click();// 下载完成后释放 URL 对象URL.revokeObjectURL(url);})},