我们经常会看到,一些报名的网站通常都会收集用户的数据,最后把数据填充到表格中以PDF的格式以便用户下载打印。他们是怎么做的呢?这个问题引起了我的兴趣,通过学习和探索,我取得了成功,下面是我的设计过程和思路:
1.使用word设计好表格并转换为PDF格式
2.使用Acrobat设计表单功能打开表格, 创建文本域并设置文本域属性
3.利用Java Map集合键值对存储的特点, 将变量值与表单文本域映射, 填充文字
4.计算图片原点位置, 根据下图(图片填充图解)的方法
5.设计接口, 从前端获取所需参数, 调通程序
6.完整代码如下:
@PostMapping("/pdf")
public Result printfPDF(@RequestBody NPCMessageRequest npcMessageRequest) throws IOException {
System.out.println("人大信息: " +npcMessageRequest);
String basicPath = System.getProperty("user.dir") ;
System.out.println("当前项目目录: " + basicPath);
final String READ_PATH = basicPath + "/人大议案管理系统人大信息一览表_read.pdf";
String WRITE_PATH = basicPath + "/PDF/" + fileName + Calendar.getInstance().getTimeInMillis() + npcMessageRequest.getId() + ".pdf";
String filePath = fileName + npcMessageRequest.getId() + ".pdf";
PdfReader pdfReader = new PdfReader(READ_PATH);
PdfWriter pdfWriter = new PdfWriter(WRITE_PATH);
PdfDocument pdfDocument = new PdfDocument(pdfReader, pdfWriter);
PdfAcroForm form = PdfAcroForm.getAcroForm(pdfDocument, false);
PdfFont font = PdfFontFactory.createFont(basicPath + "/STKAITI.TTF");
DeviceRgb color = new DeviceRgb(0, 0, 0);
//文本填充
Map<String, String> map = new HashMap<>();
map.put("name", npcMessageRequest.getName());
map.put("telephone", npcMessageRequest.getTelephone());
map.put("email", npcMessageRequest.getEmail());
map.put("motto", npcMessageRequest.getMotto());
String role = npcMessageRequest.getAddress() + "人大代表";
map.put("role", role);
map.put("time", new SimpleDateFormat("YYYY-MM-dd").format(new Date()));
System.out.println("PDF文件导出的时间为: " + new SimpleDateFormat("YYYY-MM-dd").format(new Date()));
map.put("averageRate", npcMessageRequest.getAverageRate());
for(Map.Entry<String, String> entry: map.entrySet()){
form.getFormFields()
.get(entry.getKey())
.setValue(entry.getValue())
.setColor(color)
.setFont(font);
}
//获取图片元素
PdfFormField field = form.getField("selfie");
//获取控件对象
List<PdfWidgetAnnotation> widgets = field.getWidgets();
PdfWidgetAnnotation annotation = widgets.get(0);
//域左、下角顶点坐标
float x1 = annotation.getRectangle()
.getAsNumber(0)
.floatValue();
float y1 = annotation.getRectangle()
.getAsNumber(1)
.floatValue();
//域右、上角顶点坐标
float x2 = annotation.getRectangle()
.getAsNumber(2)
.floatValue();
float y2 = annotation.getRectangle()
.getAsNumber(3)
.floatValue();
//域宽高
float fieldWidth = x2 - x1;
float fieldHeight = y2 - y1;
//创建图片对象
Image img = new Image(ImageDataFactory.create("/www/wwwroot/vue/dist/" + npcMessageRequest.getSelfie().replace("../", "")));
System.out.println("图片在本地地址: " +img);
//图片自适应缩放
Image image = img.scaleToFit(fieldWidth, fieldHeight);
//获取图片自适应缩放后的宽高
float scaleWidth = image.getImageScaledWidth();
float scaleHeight = image.getImageScaledHeight();
//计算图片中点位置
//x坐标 = 域x坐标 + (域宽度 / 2) - (自适应后图片宽度 / 2);
//y坐标 = 域y坐标 + (域高度 / 2) - (自适应后图片高度 / 2);
float centerX = x1 + (fieldWidth / 2) - (scaleWidth / 2);
float centerY = y1 + (fieldHeight / 2) - (scaleHeight / 2);
//设置图片填充位置
img.setFixedPosition(centerX, centerY);
//获取文档对象, 将图片添加到文档
Document document = new Document(pdfDocument);
document.add(img);
//清除表单中默认填充
form.flattenFields();
pdfDocument.close();
pdfReader.close();
pdfWriter.close();
String finalUrl = upload(WRITE_PATH);
return Result.success(finalUrl);
}
}