参考文章来源:
springboot+itextpdf按模板生成PDF文件及在线下载PDF文件
JAVA根据模板生成PDF文件并导出
java将字符串按照指定长度分割成字符串数组
感谢上述博主大大,救我一命~~~
我的系统环境:win10、IDEA、jdk1.8
一、Adobe Acrobat DC的下载百度链接:链接:https://pan.baidu.com/s/1RSV8D6kXDbWeV2owgw2Zyg
提取码:f8p8
可自取。
1、在word中画好模板,另存为pdf格式
我生成的pdf模板如下图所示。
2、打开软件:Adobe Acrobat DC
页面如下图所示,选择【工具】–【准备表单】
将上述pdf文件放入这里
进入编辑表单页面,编辑字段(此字段名需和程序中字段名保持一致)。我的编辑如下图所示。
由于在【备注】这一字段中,我们的要求是文字带下划线的那种,且备注文字可能会有些长,因此我在这里设置成这样,我的思路如下:
1、在Adobe Acrobat DC中设置了bz-line1、bz-line2、bz-line3三个文本域,并分别设置其属性(双击该域即可,文字大小样式等都可以设置)。如下图所示:
2、程序中,读取数据(字符串类型),按固定长度对字符串进行截取并循环放入bz-line1、bz-line2、bz-line3中。后面在程序里我会展示我使用的笨方法。。。。
3、其实。。如果没有要求带下划线的话,完全可以直接在【属性】中勾选上【多行】即可实现多文字的换行。
3、保存编辑好的模板
1、添加Maven依赖
com.itextpdf itextpdf5.5.13 com.itextpdf itext-asian5.2.0
2、直接生成pdf至本地指定路径
(1)、pdfUtils类
public class PdfUtils { private final static Logger log = LoggerFactory.getLogger(PdfUtils.class); // 利用模板生成pdf,这将直接保存到指定路径 public static void pdfout(Mapo,String templatePath,String newPDFPath) { PdfReader reader; FileOutputStream out=null; ByteArrayOutputStream bos=null; PdfStamper stamper; try { //系统字体 String prefixFont = ""; String os = System.getProperties().getProperty("os.name"); if (os.startsWith("win") || os.startsWith("Win")) { prefixFont = "C:\Windows\Fonts" + File.separator; } else { prefixFont = "/usr/share/fonts/chinese" + File.separator; } //必须加“,0”或“,1”,否则会报错:com.itextpdf.text.documentException: Font 'C:WindowsFontssimsun.ttc' with 'Identity-H' is not recognized. baseFont bf = baseFont.createFont(prefixFont + "simsun.ttc,0" , baseFont.IDENTITY_H, baseFont.EMBEDDED); out = new FileOutputStream(newPDFPath);// 输出流 reader = new PdfReader(templatePath);// 读取pdf模板 bos = new ByteArrayOutputStream(); stamper = new PdfStamper(reader, bos); AcroFields form = stamper.getAcroFields(); //文字类的内容处理 Map datemap = (Map )o.get("datemap"); form.addSubstitutionFont(bf); for(String key : datemap.keySet()){ //为了文字可以有下划线,并且换行,控制每行字数,当字数超过时,将剩余文字填充至下一备选域 if ("hzbz".equals(key)){ String hzbz = datemap.get(key); String[] hzbzArray = stringToStringArray(hzbz,24); for(int i = 0; i < hzbzArray.length; i++){ String fkey = "hzbz-line" + (i+1); form.setField(fkey,hzbzArray[i]); } }else if("bz".equals(key)){ String bz = datemap.get(key); String[] bzArray = stringToStringArray(bz,24); for(int i = 0; i < bzArray.length; i++){ String fkey = "bz-line" + (i+1); form.setField(fkey,bzArray[i]); } }else{ String value = datemap.get(key); form.setField(key,value); } } //图片类的内容处理 Map imgmap = (Map )o.get("imgmap"); for(String key : imgmap.keySet()) { Image value = imgmap.get(key); //String imgpath = value; Image image = value; 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(imgpath); //获取图片页面 PdfContentByte under = stamper.getOverContent(pageNo); //图片大小自适应 image.scaleToFit(signRect.getWidth(), signRect.getHeight()); //添加图片 image.setAbsolutePosition(x, y); under.addImage(image); } stamper.setFormFlattening(true);// 如果为false,生成的PDF文件可以编辑,如果为true,生成的PDF文件不可以编辑 stamper.close(); document doc = new document(PageSize.A4, 50, 40, 40, 50); PdfCopy copy = new PdfCopy(doc, out); doc.open(); //form.getTotalRevisions(); int pages= stamper.getReader().getNumberOfPages(); for(int i=1;i<=pages;i++){ PdfimportedPage importPage = copy.getimportedPage(new PdfReader(bos.toByteArray()), i); copy.addPage(importPage); } doc.close(); } catch (IOException e) { log.error("pdfout",e); } catch (documentException e) { log.error("pdfout",e); }finally { if(out!=null){ try{ out.close(); }catch(Exception e){ } } if(bos!=null){ try{ bos.close(); }catch(Exception e){ } } } } // 将字符串按照指定长度分割成字符串数组 public static String[] stringToStringArray(String src, int length) { //检查参数是否合法 if (null == src || src.equals("")) { return null; } if (length <= 0) { return null; } int n = (src.length() + length - 1) / length; //获取整个字符串可以被切割成字符子串的个数 String[] split = new String[n]; for (int i = 0; i < n; i++) { if (i < (n - 1)) { split[i] = src.substring(i * length, (i + 1) * length); } else { split[i] = src.substring(i * length); } } return split; } public static byte[] inputstream2Bytes(InputStream inStream) throws IOException{ byte[] in_b = null; try{ ByteArrayOutputStream swapStream = new ByteArrayOutputStream(); byte[] buff = new byte[100]; //buff用于存放循环读取的临时数据 int rc = 0; while ((rc = inStream.read(buff, 0, 100)) > 0) { swapStream.write(buff, 0, rc); } in_b = swapStream.toByteArray(); //in_b为转换之后的结果 }catch(Exception e){ log.error("inputstream2Bytes",e); }finally { inStream.close(); } return in_b; } public static InputStream file2InputStream(File file) throws IOException{ return new FileInputStream(file); }
(2)、controller层
@Controller @RequestMapping("/pdf") public class PdfController { @PostMapping("/createPdf") @ResponseBody public DataObject CreatePdf() throws AppException { //1、调用数据库,获取数据 //此处写读取数据的代码 //2、将数据存为key-value //存文字信息 Mapmap = new HashMap(); //存图像信息 Map mapI = new HashMap(); map.put("name","田XX"); map.put("sex","女"); map.put("grbh","123456789010"); map.put("sfzh","000000000000000000"); map.put("rylb","啊哦"); map.put("time1","2021-9-27"); map.put("ddyy1","啊哦"); map.put("time2",""); map.put("ddyy2",""); map.put("hzbz","有的人一生默默无闻,有的人一生轰轰烈烈,甚至千古流芳,为什么会这样?因为默默无闻的人只是满足于现状,而不去想怎么轰轰烈烈过一生,不要求自己,去做"); map.put("bz","有的人一生默默无闻,有的人一生轰轰烈烈,甚至千古流芳,为什么会这样?因为默默无闻的人只是满足于现状,而不去想怎么轰轰烈烈过一生,不要求自己,去做"); try{ //图片路径 File pic_file = new File("F:\1555074510295049.jpg"); Image pic_image = Image.getInstance(inputstream2Bytes(file2InputStream(pic_file))); mapI.put("pic",pic_image); }catch(Exception e){ } Map o=new HashMap(); o.put("datemap",map); o.put("imgmap",mapI); // 模板路径 String templatePath = "/meta-INF/resources/static/template/template.pdf"; // 生成的新文件路径 String newPDFPath = "F:\template_sc.pdf"; pdfout(o,templatePath,newPDFPath); return DataObject.getInstance(); } }
(3)前端入口
layui.sight.ajaxRequest({ type : 'post', async : true, url : layui.sight.compileUrl('${rc.contextPath}/pdf/CreatePdf'), data : [], callback : function(data) { alert("成功!") }, failedCallback : function(data) {} });
3、导出pdf
(1)pdfUtils类
public class PdfUtils { private final static Logger log = LoggerFactory.getLogger(PdfUtils.class); public static void pdfExport(Mapo, HttpServletResponse response) { // 模板路径 String templatePath = "/meta-INF/resources/static/template/template.pdf"; File file = new File(templatePath); if (!file.exists()) { try { file.createNewFile(); } catch (IOException e) { e.printStackTrace(); } } PdfReader reader; ByteArrayOutputStream bos; PdfStamper stamper; OutputStream out = null; try { baseFont bf = baseFont.createFont("C:/Windows/Fonts/simfang.ttf", baseFont.IDENTITY_H, baseFont.EMBEDDED); // 输出流 response.setContentType("application/pdf"); response.setHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode("template_scsc.pdf", "UTF-8")); out = new BufferedOutputStream(response.getOutputStream()); // 读取pdf模板 reader = new PdfReader(templatePath); bos = new ByteArrayOutputStream(); stamper = new PdfStamper(reader, bos); AcroFields form = stamper.getAcroFields(); //文字类的内容处理 Map datemap = (Map )o.get("datemap"); form.addSubstitutionFont(bf); for(String key : datemap.keySet()){ //为了文字可以有下划线,并且换行,控制每行字数,当字数超过时,将剩余文字填充至下一备选域 if ("hzbz".equals(key)){ String hzbz = datemap.get(key); String[] hzbzArray = stringToStringArray(hzbz,24); for(int i = 0; i < hzbzArray.length; i++){ String fkey = "hzbz-line" + (i+1); form.setField(fkey,hzbzArray[i]); } }else if("bz".equals(key)){ String bz = datemap.get(key); String[] bzArray = stringToStringArray(bz,24); for(int i = 0; i < bzArray.length; i++){ String fkey = "bz-line" + (i+1); form.setField(fkey,bzArray[i]); } }else{ String value = datemap.get(key); form.setField(key,value); } } //图片类的内容处理 Map imgmap = (Map )o.get("imgmap"); for(String key : imgmap.keySet()) { Image value = imgmap.get(key); //String imgpath = value; Image image = value; 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(imgpath); //获取图片页面 PdfContentByte under = stamper.getOverContent(pageNo); //图片大小自适应 image.scaleToFit(signRect.getWidth(), signRect.getHeight()); //添加图片 image.setAbsolutePosition(x, y); under.addImage(image); } stamper.setFormFlattening(true); stamper.close(); document doc = new document(); PdfCopy copy = new PdfCopy(doc, out); doc.open(); PdfimportedPage importPage = copy.getimportedPage(new PdfReader(bos.toByteArray()), 1); copy.addPage(importPage); doc.close(); } catch (IOException | documentException e) { System.out.println(e); } finally { try { assert out != null; out.close(); } catch (IOException e) { e.printStackTrace(); } } } // 将字符串按照指定长度分割成字符串数组 public static String[] stringToStringArray(String src, int length) { //检查参数是否合法 if (null == src || src.equals("")) { return null; } if (length <= 0) { return null; } int n = (src.length() + length - 1) / length; //获取整个字符串可以被切割成字符子串的个数 String[] split = new String[n]; for (int i = 0; i < n; i++) { if (i < (n - 1)) { split[i] = src.substring(i * length, (i + 1) * length); } else { split[i] = src.substring(i * length); } } return split; } public static byte[] inputstream2Bytes(InputStream inStream) throws IOException{ byte[] in_b = null; try{ ByteArrayOutputStream swapStream = new ByteArrayOutputStream(); byte[] buff = new byte[100]; //buff用于存放循环读取的临时数据 int rc = 0; while ((rc = inStream.read(buff, 0, 100)) > 0) { swapStream.write(buff, 0, rc); } in_b = swapStream.toByteArray(); //in_b为转换之后的结果 }catch(Exception e){ log.error("inputstream2Bytes",e); }finally { inStream.close(); } return in_b; } public static InputStream file2InputStream(File file) throws IOException{ return new FileInputStream(file); }
(2)、controller层
@Controller @RequestMapping("/pdf") public class PdfController { @RequestMapping("/exportPdf") public void exportPdf(HttpServletRequest request, HttpServletResponse response) throws AppException { //调用数据库,获取数据 //将数据存为key-value //存文字信息 Mapmap = new HashMap(); //存图像信息 Map mapI = new HashMap(); map.put("name","田XX"); map.put("sex","女"); map.put("grbh","12345678910"); map.put("sfzh","00000000000000000"); map.put("rylb","啊哦"); map.put("time1","2021-9-27"); map.put("ddyy1","啊哦"); map.put("time2",""); map.put("ddyy2",""); map.put("hzbz","有的人一生默默无闻,有的人一生轰轰烈烈,甚至千古流芳,为什么会这样?因为默默无闻的人只是满足于现状,而不去想怎么轰轰烈烈过一生,不要求自己,去做"); map.put("bz","有的人一生默默无闻,有的人一生轰轰烈烈,甚至千古流芳,为什么会这样?因为默默无闻的人只是满足于现状,而不去想怎么轰轰烈烈过一生,不要求自己,去做"); try{ //图片路径 File pic_file = new File("F:\1555074510295049.jpg"); Image pic_image = Image.getInstance(inputstream2Bytes(file2InputStream(pic_file))); mapI.put("pic",pic_image); }catch(Exception e){ } Map o=new HashMap(); o.put("datemap",map); o.put("imgmap",mapI); pdfExport(o,response); } }
(3)前端入口
function down(){ var url = layui.sight.compileUrl('${rc.contextPath}/pdf/exportPdf'); window.open(encodeURI(url)); }四、最终效果
图片选的不太好。。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)