html展示pdf文件流_后端导出PDF文件(付前端实现代码)

该博客介绍了如何利用前端代码通过href请求后端地址,结合FreeMarker模板和后端Java代码生成PDF文件。首先展示前端直接调用的URL,然后详细讲解了FTL模板的编写,包括设置字体、样式和内容。接着,展示了后端核心接口代码,使用Freemarker解析模板并生成PDF,最后提供了一个本地方法将HTML转换为PDF。测试时,只需在浏览器中请求指定URL即可导出PDF测试文件。
摘要由CSDN通过智能技术生成

前言

效果图:28b52c6006757a83d492553f23de7209.png

一、前端代码

// 直接用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("&nbsp", " "); 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测试文件

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值