一、前期准备
在开发中经常会遇到需要进行对一些数据进行动态导出PDF文件,然后让用户自己选择是否需要打印出来,这篇文章我们来用个相对来说比较简单的方式来实现PDF动态导出;
导入依赖 SpringBoot版本2.0.5.RELEASE
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-freemarker</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.20</version></dependency><dependency><groupId>com.itextpdf</groupId><artifactId>html2pdf</artifactId><version>4.0.3</version></dependency>
二、代码实现) 先准备一个html,这个html是一个模板,是将我们需要动态展示的数据插入到每个占位符进来,如下:
先准备一个html,这个html是一个模板,是将我们需要动态展示的数据插入到每个占位符进来,如下:
<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"/><title>Title</title><style>body{font-size: 15px;}.title{text-align: center;}.content{margin:0 auto;width: 400px;}.content .text{text-indent: 2em;}.content .datetime{text-align: right;}</style></head><body><div><divclass="view"><h2class="title">自我介绍</h2><divclass="content"><pclass="text">
大家好,我叫${person.personName},我今年${person.personAge},我是个${person.personGender},
我的职业是${person.personVocation},我目前住在${person.address},我在性格方面${person.personalityDesc}。
</p><pclass="datetime">${person.createTime}</p></div></div></div></body></html>
在准备一个PDFUtil的工具类
PDFUtil工具类
publicclassPdfUtil{@AutowiredprivateConfiguration configuration;/**
* 获取模板内容
* @param templateDirectory 模板文件夹
* @param templateName 模板文件名
* @param paramMap 模板参数
* @return
* @throws Exception
*/publicstaticStringgetTemplateContent(String templateDirectory,String templateName,Map<String,Object> paramMap)throwsException{Configuration configuration =newConfiguration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);try{
configuration.setDirectoryForTemplateLoading(newFile(templateDirectory));}catch(Exception e){System.out.println("-- exception --");}Writer out =newStringWriter();Template template = configuration.getTemplate(templateName,"UTF-8");
template.process(paramMap, out);
out.flush();
out.close();return out.toString();}/**
* HTML 转 PDF
* @param content html内容
* @param outPath 输出pdf路径
* @return 是否创建成功
*/publicstaticbooleanhtml2Pdf(String content,String outPath){try{ConverterProperties converterProperties =newConverterProperties();
converterProperties.setCharset("UTF-8");FontProvider fontProvider =newFontProvider();
fontProvider.addSystemFonts();
converterProperties.setFontProvider(fontProvider);HtmlConverter.convertToPdf(content,newFileOutputStream(outPath), converterProperties);}catch(Exception e){
log.error("生成模板内容失败,{}",e);returnfalse;}returntrue;}/**
* HTML 转 PDF
* @param content html内容
* @return PDF字节数组
*/publicstaticbyte[]html2Pdf(String content){ByteArrayOutputStream outputStream =newByteArrayOutputStream();try{ConverterProperties converterProperties =newConverterProperties();
converterProperties.setCharset("UTF-8");FontProvider fontProvider =newFontProvider();
fontProvider.addSystemFonts();
converterProperties.setFontProvider(fontProvider);HtmlConverter.convertToPdf(content,outputStream,converterProperties);}catch(Exception e){
log.error("生成 PDF 失败,{}",e);}return outputStream.toByteArray();}}Bean类
```java
@DatapublicclassPersonIntroduce{//名称privateString personName ;//年龄privateInteger personAge ;//性格描述privateString personalityDesc;//性别privateString personGender;//职业privateString personVocation;//现居地址privateString address;//创建时间privateString createTime;}
Controller层代码
@ControllerpublicclassPersonIntroduceController{@AutowiredprivatePersonIntroduceService personIntroduceService;@GetMapping("/exPdf")@ResponseBodypublicvoidexPdfPersonIntroduce(HttpServletRequest request ,HttpServletResponse response)throwsTemplateException,IOException{PersonIntroduce personIntroduce =newPersonIntroduce();
personIntroduce.setPersonName("小刘");
personIntroduce.setAddress("北京朝阳区");
personIntroduce.setPersonAge(24);
personIntroduce.setPersonGender("男生");
personIntroduce.setPersonalityDesc("其实我也不是很清楚");
personIntroduce.setPersonVocation("Java后端开发");
personIntroduceService.exPersonIntroduce(personIntroduce , request , response);}}
Service业务层代码:
注意:建议使用这种方式,之前我在项目开发的过程中,使用了PdUtil.class.ClassLoader()这种方式去定位exPdf.html,在线下(开发环境)是可以使用的,但是部署到服务器的时候就出现了文件找不到的情况,因为上述这种方式他是使用的磁盘绝对路径查找的。使用freeMarkerConfigurer.getConfiguration().getTemplate(“exPdf.html”);来定位就不会出现这种问题。
@ServicepublicclassPersonIntroduceServiceImplimplementsPersonIntroduceService{@AutowiredprivateFreeMarkerConfigurer freeMarkerConfigurer;/**
* PDF导出类
* @param personIntroduce
*/publicvoidexPersonIntroduce(PersonIntroduce personIntroduce ,HttpServletRequest request,HttpServletResponse response)throwsIOException,TemplateException{SimpleDateFormat sdf =newSimpleDateFormat("yyyy年MM月dd日");Map<String,Object> paramMap =newHashMap<>();
personIntroduce.setCreateTime(sdf.format(newDate()));
paramMap.put("person", personIntroduce);Writer out =newStringWriter();//获取模板地址Template template = freeMarkerConfigurer.getConfiguration().getTemplate("exPdf.html");
template.process(paramMap, out);
out.flush();
out.close();String templateContent = out.toString();
response.setCharacterEncoding("UTF-8");
response.setContentType("application/pdf");String fileName =personIntroduce.getPersonName()+"-个人介绍-"+ sdf.format(newDate());
response.setHeader("Content-Disposition","filename="+newString(fileName.getBytes(),"iso8859-1"));byte[] resources =PdfUtil.html2Pdf(templateContent);ServletOutputStream outputStream = response.getOutputStream();
outputStream.write(resources);
outputStream.close();}}
项目结构:
三、使用
这样就Ok了
版权归原作者 Netty. 所有, 如有侵权,请联系我们删除。