前言
效果图:
一、前端代码
// 直接用href请求后端地址即可window.location.href = http://localhost:8989/exportPdf;
二、使用步骤
1. ftl模板
注意:贴出的接口代码,读取的ftl模板的路径是,src\main\resources\templates\free.ftl
<#-- 如果值为null/空,则设置为空值 --><html lang="en"><head> <meta charset="UTF-8"> <title>Freemarkertitle> <style type="text/css"> #all { width: 600px; <#-- 使文档在pdf页面居中 --> margin: auto; } table { width: 100%; height: auto; <#-- @@提醒@@:此处必须指定字体,不然不识别中文 --> font-family: SimSun; text-align: center; <#-- table中单元格自动换行 --> table-layout: fixed; word-wrap: break-word; } tr td { padding: 2px; font-size: 10px; height: 20px; } tr th { padding: 2px; font-weight: bold; font-size: 10px; height: 20px; }style>head><body><div id="all"> <table border="1" cellspacing="0" cellpadding="0" align="center"> <tr> <th colspan="5">${title}th> tr> <tr> <#-- 动态获取params的大小size --> <th rowspan="${params?size+1}">基本信息th> <td>姓名td> <td>电话td> <td>昵称td> <td>邮箱td> tr> <#list params as param> <tr> <td>${param.name}td> <td>${param.phone}td> <td>${param.nickname}td> <td>${param.email}td> tr> #list> table>div>body>html>
2.后端代码
2.1 核心接口代码
package com.example.export;import cn.hutool.core.io.FileUtil;import cn.hutool.core.io.IoUtil;import freemarker.template.Configuration;import freemarker.template.Template;import lombok.extern.slf4j.Slf4j;import org.springframework.http.HttpHeaders;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpServletResponse;import java.io.*;import java.net.URLEncoder;import java.util.Arrays;import java.util.HashMap;import java.util.List;import java.util.Map;/** * 导出pdf * */@Slf4j@RestControllerpublic class ExportPdf { @GetMapping("/exportPdf") public void exportPdf(HttpServletResponse response) { // ========== pdf处理方式 =========== Map<String, Object> map1 = new HashMap<>(); map1.put("name", "赵小刚"); map1.put("phone", "15673890987"); map1.put("nickname", "红孩儿"); map1.put("email", "15673890987@163.com"); Map<String, Object> map2 = new HashMap<>(); map2.put("name", "赵小刚"); map2.put("phone", "15673890987"); map2.put("nickname", "红孩儿"); map2.put("email", "15673890987@163.com"); List<Map<String, Object>> stuffList = Arrays.asList(map1,map2); Map<String, Object> stuffMap = new HashMap<>(); stuffMap.put("params", stuffList); stuffMap.put("title", "测试PDF模板"); File pdfFile = FileUtil.file("test.pdf"); try (OutputStream os = new FileOutputStream(pdfFile);) { Configuration cfg = new Configuration(Configuration.VERSION_2_3_30); // 如果填充值中与模板不匹配,或者为null值,则默认此值为空; cfg.setClassicCompatible(true); // 模板路径加载方式:基于类路径,即在src\main\resources\templates包下的ftl模板 cfg.setClassForTemplateLoading(this.getClass(),"/templates"); Template template = cfg.getTemplate( "pdf.ftl"); Writer writer = new StringWriter(); template.process(stuffMap, writer); // 对pdf资料进行创建 HtmlToPdf.htmlToPdf(writer.toString(),os); byte[] dataByte = FileUtil.readBytes(pdfFile); response.addHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(dataByte.length)); response.setHeader(HttpHeaders.CONTENT_DISPOSITION, String.format("attachment; filename=%s" , URLEncoder.encode("pdf测试.pdf", "UTF-8"))); IoUtil.write(response.getOutputStream(), Boolean.TRUE, dataByte); } catch (Exception e) { log.error("导出贷后检查表失败, 详情:{}", e.getMessage()); } finally { // 删除项目classes/目录下生成的临时文件 if (pdfFile.exists()) { FileUtil.del(pdfFile); } } }}
2.2 本地方法 HtmlToPdf.htmlToPdf()
/** * 将HTML转成PD格式的文件。html文件的格式比较严格 * @param htmlText html内容 * @param os pdf存储文件输出流, 需要调用方关闭流 * @throws Exception */ public static void htmlToPdf(String htmlText, OutputStream os) throws Exception { // 没有闭合标签,故删掉 htmlText = htmlText.replace("", StrUtil.EMPTY); Document document = Jsoup.parse(htmlText); /*手动为一些标签添加闭合*/ Elements meta = document.getElementsByTag("meta"); String html = document.html(); for (Element link : meta) { String s = link.outerHtml(); String s1 = s.replace("/>", ">"); html = html.replace(s, s1 + ""); } Elements link1 = document.getElementsByTag("link"); for (Element link : link1) { String s = link.outerHtml(); String s1 = s.replace("/>", ">"); html = html.replace(s, s1 + ""); } html = html.replaceAll("
", "
"); html = html.replaceAll(" ", " "); ITextRenderer renderer = new ITextRenderer(); renderer.setDocumentFromString(html); // 解决中文支持, 注意本地和生产必须有此字体文件 ITextFontResolver fontResolver = renderer.getFontResolver(); String currentSystem = System.getProperty("os.name").toLowerCase(); if("linux".equals(currentSystem)){ fontResolver.addFont("/usr/share/fonts/chinese/simsun.ttc", BaseFont.IDENTITY_H, BaseFont.EMBEDDED); }else{ fontResolver.addFont("C:/Windows/Fonts/simsun.ttc", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED); } renderer.layout(); renderer.createPDF(os); }
3.测试
启动项目,使用浏览器请求:http://localhost:8989/exportPdf
即可实现导出pdf测试文件