一、前期准备
在开发中经常会遇到需要进行对一些数据进行动态导出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是一个模板,是将我们需要动态展示的数据插入到每个占位符进来,如下:
DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"/> <title>Titletitle> <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> <div class="view"> <h2 class="title">自我介绍h2> <div class="content"> <p class="text"> 大家好,我叫${person.personName},我今年${person.personAge},我是个${person.personGender}, 我的职业是${person.personVocation},我目前住在${person.address},我在性格方面${person.personalityDesc}。 p> <p class="datetime">${person.createTime}p> div> div>div>body>html>
在准备一个PDFUtil的工具类
PDFUtil工具类
public class PdfUtil { @Autowired private Configuration configuration; public static String getTemplateContent(String templateDirectory, String templateName, Map<String, Object> paramMap) throws Exception { Configuration configuration = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS); try { configuration.setDirectoryForTemplateLoading(new File(templateDirectory)); } catch (Exception e) { System.out.println("-- exception --"); } Writer out = new StringWriter(); Template template = configuration.getTemplate(templateName,"UTF-8"); template.process(paramMap, out); out.flush(); out.close(); return out.toString(); } public static boolean html2Pdf(String content, String outPath) { try { ConverterProperties converterProperties = new ConverterProperties(); converterProperties.setCharset("UTF-8"); FontProvider fontProvider = new FontProvider(); fontProvider.addSystemFonts(); converterProperties.setFontProvider(fontProvider); HtmlConverter.convertToPdf(content, new FileOutputStream(outPath), converterProperties); } catch (Exception e) { log.error("生成模板内容失败,{}",e); return false; } return true; } public static byte[] html2Pdf(String content) { ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); try { ConverterProperties converterProperties = new ConverterProperties(); converterProperties.setCharset("UTF-8"); FontProvider fontProvider = new FontProvider(); fontProvider.addSystemFonts(); converterProperties.setFontProvider(fontProvider); HtmlConverter.convertToPdf(content,outputStream,converterProperties); } catch (Exception e) { log.error("生成 PDF 失败,{}",e); } return outputStream.toByteArray(); }}Bean类```java@Datapublic class PersonIntroduce { //名称 private String personName ; //年龄 private Integer personAge ; //性格描述 private String personalityDesc; //性别 private String personGender; //职业 private String personVocation; //现居地址 private String address; //创建时间 private String createTime;}
Controller层代码
@Controllerpublic class PersonIntroduceController { @Autowired private PersonIntroduceService personIntroduceService; @GetMapping("/exPdf") @ResponseBody public void exPdfPersonIntroduce(HttpServletRequest request , HttpServletResponse response) throws TemplateException, IOException { PersonIntroduce personIntroduce = new PersonIntroduce(); 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”);来定位就不会出现这种问题。
@Servicepublic class PersonIntroduceServiceImpl implements PersonIntroduceService { @Autowired private FreeMarkerConfigurer freeMarkerConfigurer; public void exPersonIntroduce(PersonIntroduce personIntroduce , HttpServletRequest request, HttpServletResponse response) throws IOException, TemplateException { SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日"); Map<String, Object> paramMap = new HashMap<>(); personIntroduce.setCreateTime(sdf.format(new Date())); paramMap.put("person" , personIntroduce); Writer out = new StringWriter(); //获取模板地址 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(new Date()); response.setHeader("Content-Disposition", "filename=" + new String(fileName.getBytes(), "iso8859-1")); byte[] resources = PdfUtil.html2Pdf(templateContent); ServletOutputStream outputStream = response.getOutputStream(); outputStream.write(resources); outputStream.close(); }}
项目结构:
三、使用
这样就Ok了
来源地址:https://blog.csdn.net/JAVA_EE_J/article/details/130035074