java利用Freemarker模板生成pdf文档

tech2023-09-16  80

一.背景

1.公司给一个.doc的文档.让我动态生成pdf文件.在网上试了好多方法,感觉全是坑.最终采用了用xdocreport转化成pdf.

二.实现

(一).实现步骤

1.把.doc文件字体全部改成宋体 2.把.doc文件另存为.docx文件 3.将.docx文件后缀名改为.zip 4.解压zip文件,找到word文件夹里面的document.xml文件.及_rels文件夹下的document.xml.rels文档 5.修改document.xml,以及document.xml.rels 6.代码实现转pdf

(二).修改document.xml

这是原本.doc文档目录,首选我们要遍历数据,填充目录

找到2.0草池变-缺陷报告下面的段落进行遍历,遍历方式如图所示.数据结构为.Map里面套List,List里面再套Map,如下图数据结构

/** 在ftl文件中有${textDeal}这个标签**/ Map<String,Object> dataM = new HashMap<String, Object>(); List<Map<String, Object>> mapList = new ArrayList<Map<String, Object>>(); int j = 1; for (int i = 0; i < 10; i++) { Map<String,Object> dataMap = new HashMap<String, Object>(); dataMap.put("id",j+""); j++; dataMap.put("stationName","草池变"); dataMap.put("irImgUrl","D:/10kV穿墙套管-small.jpg"); dataMap.put("viImgUrl","D:/35kV穿墙套管-small-vi.jpg"); mapList.add(dataMap); } dataM.put("mapList",mapList); dataM.put("stationName", "草池变"); dataM.put("deviceVoltage", "110kv");

<w:hyperlink w:anchor 相当于一个指针 指向名称为${‘2.’+(dataMap_index+1)+’ ‘+dataMap.stationName+’-’+dataMap.deviceName+‘缺陷报告’}的段落

这里修改成如上一样(不知道这是什么) 找到该段落为3的页码数改成如下图

到这里我们目录就遍历完成下面我们遍历正文

如上图表格我们是要循环遍历的包括(2.1 草池变-3号电容器组电抗器-缺陷报告) 我们找到document.xml的所在位置进行遍历

w:id抱着不重复就行,w:name对应目录,实现点击目录就能跳转到此 document.xml图片替换 , 第一行 id,name不重复即可.重要在最后一行r:embed对应的是document.xml.rels里面的图片.

这样它就会在media目录下找到该图片 分页如下图所示

如果有数据则进行分页<#if>包着那一段

(三).代码实现(包含浏览器导出代码)

//获取dataMap数据 List<Map<String, Object>> mapList = (List<Map<String, Object>>)dataMapList.get("mapList"); //产生一个随机数(用于拼接文件名) String random = IdUtil.objectId(); try { /** 初始化配置文件 **/ Configuration configuration = new Configuration(); String fileDirectory = basePath; /** 加载文件 **/ configuration.setDirectoryForTemplateLoading(new File(fileDirectory)); /** 加载模板 **/ Template template = configuration.getTemplate("document.xml"); Template templateRels = configuration.getTemplate("document.xml.rels"); /** 指定输出word文件的路径 **/ String outFilePath = basePath+random+"data.xml"; File docFile = new File(outFilePath); FileOutputStream fos = new FileOutputStream(docFile); Writer out = new BufferedWriter(new OutputStreamWriter(fos),10240); template.process(dataMapList,out); if(out != null){ out.close(); } String outFilePathRels = basePath+random+"dataRels.xml"; File docFileRels = new File(outFilePathRels); FileOutputStream fosRels = new FileOutputStream(docFileRels); Writer outRels = new BufferedWriter(new OutputStreamWriter(fosRels),10240); templateRels.process(dataMapList,outRels); if(outRels != null){ outRels.close(); } ZipInputStream zipInputStream = ZipUtils.wrapZipInputStream(new FileInputStream(new File(basePath+"红外缺陷报告.zip"))); ZipOutputStream zipOutputStream = ZipUtils.wrapZipOutputStream(new FileOutputStream(new File(basePath+random+"红外缺陷报告.docx"))); //开始覆盖文档------------------ int len; byte[] buffer = new byte[1024]; //写入图片 for (Map<String, Object> dataMap : mapList) { ZipEntry irImageNext = new ZipEntry("word" + File.separator + "media" + File.separator + "ir"+dataMap.get("id")+".jpeg"); zipOutputStream.putNextEntry(new ZipEntry(irImageNext.toString())); //获取图片byte数组 byte[] irImageBytes = FileUtils.getImgBytes("1",(String)dataMap.get("irImgUrl")); //获取图片流 InputStream irIn = new ByteArrayInputStream(irImageBytes); while ((len = irIn.read(buffer)) != -1) { zipOutputStream.write(buffer, 0, len); } irIn.close(); ZipEntry viImageNext = new ZipEntry("word" + File.separator + "media" + File.separator + "vi"+dataMap.get("id")+".jpeg"); zipOutputStream.putNextEntry(new ZipEntry(viImageNext.toString())); byte[] viImageBytes = FileUtils.getImgBytes("1",(String)dataMap.get("viImgUrl")); InputStream viIn = new ByteArrayInputStream(viImageBytes); while ((len = viIn.read(buffer)) != -1) { zipOutputStream.write(buffer, 0, len); } viIn.close(); } //document.xml和document.xml.rels替换 String itemname = "word/document.xml"; String relsName = "word/_rels/document.xml.rels"; ZipUtils.replaceItems(zipInputStream, zipOutputStream, itemname,relsName, new FileInputStream(new File(basePath+random+"data.xml")), new FileInputStream(new File(basePath+random+"dataRels.xml"))); System.out.println("success"); } catch (Exception e) { e.printStackTrace(); } long startTime=System.currentTimeMillis(); try { XWPFDocument document=new XWPFDocument(new FileInputStream(new File(basePath+random+"红外缺陷报告.docx"))); // document.setParagraph(new Pa ); File outFile=new File(basePath+random+"红外缺陷报告.pdf"); outFile.getParentFile().mkdirs(); OutputStream output=new FileOutputStream(outFile); // IFontProvider fontProvider = new AbstractFontRegistry(); PdfOptions options= PdfOptions.create(); //gb2312 PdfConverter.getInstance().convert(document,output,options); } catch ( Exception e) { e.printStackTrace(); } System.out.println("Generate ooxml.pdf with " + (System.currentTimeMillis() - startTime) + " ms."); //下载pdf InputStream fin = null; ServletOutputStream out = null; try { fin = new FileInputStream(new File(basePath+random+"红外缺陷报告.pdf")); response.setCharacterEncoding("utf-8"); response.setContentType("application/pdf"); response.addHeader("Content-Disposition", "attachment;filename=" + new String(("红外缺陷报告" + ".pdf").getBytes("GB2312"), "iso8859-1") + ""); out = response.getOutputStream(); byte[] buffer = new byte[1024];// 缓冲区 int bytesToRead = -1; // 通过循环将读入的Word文件的内容输出到浏览器中 while ((bytesToRead = fin.read(buffer)) != -1) { out.write(buffer, 0, bytesToRead); } fin.close(); out.close(); // file.delete(); } catch (Exception ex) { ex.printStackTrace(); } finally { ZipUtils.close(fin); ZipUtils.close(out); } /*//删除相关文件 FileUtils.deleteFile(basePath+random+"红外缺陷报告.docx"); FileUtils.deleteFile(basePath+random+"data.xml"); FileUtils.deleteFile(basePath+random+"红外缺陷报告.pdf"); FileUtils.deleteFile( basePath+random+"dataRels.xml");*/ return response;

注:D:/bb目录文件如下图所示 中间参考链接:

https://www.cnblogs.com/suzan/p/10577738.html https://my.oschina.net/u/3737136/blog/2958421?tdsourcetag=s_pcqq_aiomsg

最新回复(0)