package com.ruoyi.service.impl; import com.itextpdf.text.DocumentException; import com.itextpdf.text.Image; import com.itextpdf.text.Rectangle; import com.itextpdf.text.pdf.*; import com.ruoyi.domain.vo.PhotoStorageVO; import com.ruoyi.service.PdfTemplateManagementService; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.servlet.http.HttpServletResponse; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; import java.lang.reflect.Field; import java.util.Map; /** * PDF模板管理Service业务层处理 * @author gxk */ @Service @Transactional public class PdfTemplateManagementServiceImpl implements PdfTemplateManagementService { /** * 检验报告PDF下载 * @param response */ @Override public void generateInspectionReport(HttpServletResponse response) throws Exception { PdfReader reader = null; PdfStamper ps = null; OutputStream fos = null; ByteArrayOutputStream bos = null; try { // 模板绝对路径--服务器 String fileName = "/template/receipt_template_02_27.pdf"; // 读取现有模板内容 reader = new PdfReader(fileName); // 创建输出流 bos = new ByteArrayOutputStream(); // 实例化PdfStamper准备编辑pdf内容 ps = new PdfStamper(reader, bos); // 获取表单所有元素 AcroFields fields = ps.getAcroFields(); // 设置具体字体格式的编码, 不设置的话中文可能不会显示 BaseFont bf = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED); fields.addSubstitutionFont(bf); // 渲染 // fillData(fields, map, ps); renderData(fields); PhotoStorageVO photoStorageVO = new PhotoStorageVO(); Class<? extends PhotoStorageVO> aClass = photoStorageVO.getClass(); Field[] declaredFields = aClass.getDeclaredFields(); for (Field field : declaredFields) { String name = field.getName(); System.out.println(name); } //必须要调用这个,否则文档不会生成的 ps.setFormFlattening(true); if(ps != null){ ps.close(); } //生成pdf路径存放的路径 fos = response.getOutputStream(); fos.write(bos.toByteArray()); }catch (Exception e){ e.printStackTrace(); }finally { if(fos!=null){ fos.flush(); fos.close(); } if (bos != null){ bos.close(); } if(reader != null){ reader.close(); } } } /** * 渲染数据 * @param fields */ private void renderData(AcroFields fields) { } /** * 填充模板中的数据 * @param fields * @param data 是一个Map<String,String> 主要存储 key 表单模板中的单元格名 value为想要赋的值,遍历 * @param ps */ public void fillData(AcroFields fields, Map<String, String> data, PdfStamper ps) { try { for (String key : data.keySet()) { String value = data.get(key); if (key.contains("image")) { addImageToPdf(key, fields, ps, value); continue; } // 为字段赋值,注意字段名称是区分大小写的 fields.setField(key, value); } } catch (Exception e) { e.printStackTrace(); } } /** * 添加图片 * @param key 应为模板名 * @param form 动态字段 * @param stamper * @param filePath 本地图片路径 * @throws DocumentException * @throws IOException * @throws IOException */ private static void addImageToPdf(String key,AcroFields form, PdfStamper stamper, String filePath) throws DocumentException, IOException, IOException { // 通过图片域名获取所在页和坐标,左下角为起点 int pageNo = form.getFieldPositions(key).get(0).page; Rectangle signRect = form.getFieldPositions(key).get(0).position; float x = signRect.getLeft(); float y = signRect.getBottom(); // 读图片 Image image = Image.getInstance(filePath); // 获取操作的页面 PdfContentByte under = stamper.getOverContent(pageNo); // 根据域的大小缩放图片 image.scaleToFit(signRect.getWidth() * 2, signRect.getHeight()); // 添加图片并设置位置(个人通过此设置使得图片垂直水平居中,可参考,具体情况已实际为准) image.setAbsolutePosition(x, y); under.addImage(image); } /** * 通过属性名获取属性在对象里的值 * @param obj * @param propertyName * @return * @param <T> */ public static <T> T getPropertyValue(Object obj, String propertyName) { try { // 获取对象的类 Class<?> objClass = obj.getClass(); // 获取类的指定属性 Field field = objClass.getDeclaredField(propertyName); // 设置属性为可访问 field.setAccessible(true); // 获取属性的值 @SuppressWarnings("unchecked") T value = (T) field.get(obj); return value; } catch (Exception e) { e.printStackTrace(); return null; } } }