1. 制作pdf模板
使用Adobe Acrobat打开pdf文件,在需要填充文字、或者图片的地方插入表单,如下图
这里只截图了一部分,其他类似
2. 添加itextpdf依赖
3. 编写工具类,根据模板,替换文字和图片,生成pdf文件
/** * 根据模板生成pdf * @param data 数据 * @param imageMap 图片数据 * @param outfile 生成文件 * @param templateFile 模板文件 * @return 文件保存全路径文件 */ public static File createPDF(Mapdata, Map imageMap, String outfile, String templateFile) { PdfReader reader = null; AcroFields s; PdfStamper ps; ByteArrayOutputStream bos = null; //输出文档路径及名称 File outFile = new File(outfile); try { reader = new PdfReader(templateFile); bos = new ByteArrayOutputStream(); ps = new PdfStamper(reader, bos); s = ps.getAcroFields(); // 处理文字 for (String key : data.keySet()) { if (data.get(key) != null) { s.setField(key, data.get(key).toString()); } } // 处理图片 for (String key : imageMap.keySet()) { String value = imageMap.get(key); String imgpath = value; int pageNo = s.getFieldPositions(key).get(0).page; Rectangle signRect = s.getFieldPositions(key).get(0).position; float x = signRect.getLeft(); float y = signRect.getBottom(); // 根据路径读取图片 Image image = Image.getInstance(imgpath); // 获取图片页面 PdfContentByte under = ps.getOverContent(pageNo); // 图片大小自适应 image.scaleToFit(signRect.getWidth(), signRect.getHeight()); // 设置图片位置,以为我们以左下角为起始点,所以这里x、y加上偏移量,偏移量为计算的居中量 image.setAbsolutePosition(x + (signRect.getWidth()-image.getScaledWidth())/2, y + (signRect.getHeight()-image.getScaledHeight())/2); // 添加图片 under.addImage(image); } // 如果为false那么生成的PDF文件还能编辑,一定要设为true ps.setFormFlattening(true); ps.close(); //生成pdf路径存放的路径 OutputStream fos = new FileOutputStream(outfile); fos.write(bos.toByteArray()); fos.flush(); fos.close(); bos.close(); } catch (IOException | DocumentException e) { log.error("读取文件异常"); e.printStackTrace(); } finally { try { bos.close(); reader.close(); } catch (IOException e) { log.error("关闭流异常"); e.printStackTrace(); } } return outFile; }
4. 测试,图片可以为网络图片,也可以为本机图片
public static void main(String[] args) { String templatePath ="D:"+File.separator+"temp"+File.separator+"ftl"+File.separator+"report.pdf"; String outPath = "D:"+File.separator+"temp"+File.separator+"report"+File.separator+"test.pdf"; MapdataMap = new HashMap<>(10); dataMap.put("qymc", "XX市申海机械设备股份有限公司"); dataMap.put("qyjc","申海机械"); dataMap.put("qymc1","XX市申海机械设备股份有限公司"); dataMap.put("qyjc1","申海机械"); dataMap.put("kkbxjz","330.89万元"); dataMap.put("ppjz","334.74万元"); dataMap.put("jzryear","2020"); dataMap.put("jzrmonth","12"); dataMap.put("jzrday","31"); dataMap.put("beginyear","2021"); dataMap.put("beginmonth","06"); dataMap.put("beginday","05"); dataMap.put("endyear","2022"); dataMap.put("endmonth","06"); dataMap.put("endday","04"); dataMap.put("k","0.2290"); dataMap.put("zhzs","0.2780"); dataMap.put("q","0.3468"); dataMap.put("w","0.2775"); dataMap.put("s","0.2710"); dataMap.put("pjdx","XX市申海机械设备股份有限公司"); dataMap.put("kkbxjz1","330.89万元"); dataMap.put("ppjz1","334.74万元"); dataMap.put("jzr","2020年12月31日"); dataMap.put("kkbxjz2","330.89万元"); dataMap.put("wtf","太原市申海机械设备股份有限公司"); dataMap.put("pjdx1","申海机械"); dataMap.put("jzr1","2020年12月31日"); dataMap.put("bzrq","2021.06.06"); dataMap.put("zsbh","AP2021_06023"); dataMap.put("yxq","2022.06.04"); Map imageMap = new HashMap<>(5); imageMap.put("logo","http://192.168.50.250:9000/group3/202111/logo.png"); imageMap.put("yqsy","D:/temp/yqsy.png"); imageMap.put("jzwd","D:/temp/jzwd.png"); imageMap.put("logo1","http://192.168.50.250:9000/group3/202111/logo.png"); imageMap.put("qrcode","D:/temp/qrcode.png"); try { createPDF(dataMap,imageMap,outPath,templatePath); } catch (Exception e) { e.printStackTrace(); } }