使用这个库的初衷

找阿里编程规范的时候在github上搜索到的,觉得pdf像书籍一样的翻页比较自由,也是手痒吧。
启发开源项目github-pdf-demo

国人的EditMD比较不错我弄了一个MarkDown写作

页面是自己凑凑的看一下图:







pdf模板页面

<!DOCTYPE html>
<html>
<head lang="en"><title>${title} - PDF</title><link href="http://localhost:8080/bootstrap/css/bootstrap.min.css" rel="stylesheet" type="text/css"/><link href="http://localhost:8080/css/pdfPage.css" rel="stylesheet" type="text/css"/><link href="http://localhost:8080/editormd/css/editormd.css" rel="stylesheet" type="text/css"/><style>@page {size:210mm 297mm; /*设置纸张大小:A4(210mm 297mm)、A3(297mm 420mm) 横向则反过来*/margin:0.25in;padding:1em;@bottom-center {content:"Bamboo © 版权所有";font-family:SimSun;font-size:12px;color:#000;};@top-center{content: element(header)};@bottom-right{content: "第" counter(page) "页  共 " counter(pages) "页";font-family: SimSun;font-size: 12px;color: #000;};}</style>
</head>
<body style="font-family: SimSun;">
<div class="container"><div class="projects-header page-header"><h2 id="pdftitle" class="text-center" style=" width: 70%;">${title!获取标题失败}</h2><p id="pdflen" class="text-center" style=" width: 70%;">字数:${len!'0'}</p></div><div class="row" style="white-space:normal;word-wrap:break-word;word-break:break-all;width: 70%;">${content!'获取内容失败'}</div></div>
</body>
</html>

github项目工具类

package com.bamboo.markdown.paper.common;import com.lowagie.text.DocumentException;
import com.lowagie.text.pdf.BaseFont;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
import org.w3c.dom.Document;
import org.xhtmlrenderer.pdf.ITextFontResolver;
import org.xhtmlrenderer.pdf.ITextRenderer;import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.*;
import java.util.List;
import java.util.Map;/*** Created by admin on 2018/6/18.* ftl模板转pdf处理工具类*/
public class FtlTransPdfUtils {private static final Logger LOGGER = LoggerFactory.getLogger(FtlTransPdfUtils.class);/*** 按模板和参数生成html字符串,再转换为flying-saucer识别的Document**@param templateName freemarker模板名称*@param variables    freemarker模板参数*@return Document*/private static Document generateDoc(FreeMarkerConfigurer configurer, String templateName, Map<String, Object> variables) {Template tp;try {tp = configurer.getConfiguration().getTemplate(templateName);} catch (IOException e) {LOGGER.error(e.getMessage(), e);return null;}StringWriter stringWriter = new StringWriter();try (BufferedWriter writer = new BufferedWriter(stringWriter)) {try {tp.process(variables, writer);writer.flush();} catch (TemplateException e) {LOGGER.error("模板不存在或者路径错误", e);} catch (IOException e) {LOGGER.error("IO异常", e);}DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();return builder.parse(new ByteArrayInputStream(stringWriter.toString().getBytes()));} catch (Exception e) {LOGGER.error(e.getMessage(), e);return null;}}/*** 核心: 根据freemarker模板生成pdf文档**@param configurer   freemarker配置*@param templateName freemarker模板名称*@param out          输出流*@param listVars     freemarker模板参数*@throws Exception 模板无法找到、模板语法错误、IO异常*/private static void generateAll(FreeMarkerConfigurer configurer, String templateName, OutputStream out, List<Map<String, Object>> listVars) {if (CollectionUtils.isEmpty(listVars)) {LOGGER.warn("警告:freemarker模板参数为空!");return;}ITextRenderer renderer = new ITextRenderer();Document doc = generateDoc(configurer, templateName, listVars.get(0));renderer.setDocument(doc, null);//设置字符集(宋体),此处必须与模板中的<body style="font-family: SimSun">一致,区分大小写,不能写成汉字"宋体"ITextFontResolver fontResolver = renderer.getFontResolver();try {fontResolver.addFont("typeface/simsun.ttc", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);} catch (DocumentException e) {LOGGER.error("S1DocumentException" + e.getMessage());} catch (IOException e) {LOGGER.error("S2IOException" + e.getMessage());}//展现和输出pdfrenderer.layout();try {renderer.createPDF(out, false);} catch (DocumentException e) {LOGGER.error("S3DocumentException" + e.getMessage());}//根据参数集个数循环调用模板,追加到同一个pdf文档中//(注意:此处从1开始,因为第0是创建pdf,从1往后则向pdf中追加内容)for (int i = 1; i < listVars.size(); i++) {Document docAppend = generateDoc(configurer, templateName, listVars.get(i));renderer.setDocument(docAppend, null);renderer.layout();try {renderer.writeNextDocument(); //写下一个pdf页面} catch (DocumentException e) {LOGGER.error("S4DocumentException" + e.getMessage());}}renderer.finishPDF(); //完成pdf写入}/*** pdf下载**@param configurer   freemarker配置*@param templateName freemarker模板名称(带后缀.ftl)*@param listVars     模板参数集*@param response     HttpServletResponse*@param fileName     下载文件名称(带文件扩展名后缀)*/public static void download(FreeMarkerConfigurer configurer, String templateName, List<Map<String, Object>> listVars, HttpServletResponse response, String fileName) {// 设置编码、文件ContentType类型、文件头、下载文件名response.setCharacterEncoding("utf-8");response.setContentType("multipart/form-data");try {response.setHeader("Content-Disposition", "attachment;fileName=" +new String(fileName.getBytes("gb2312"), "ISO8859-1"));} catch (UnsupportedEncodingException e) {LOGGER.error("X1" + e.getMessage());}try (ServletOutputStream out = response.getOutputStream()) {generateAll(configurer, templateName, out, listVars);out.flush();} catch (Exception e) {LOGGER.error("X2" + e.getMessage());//X2java.io.IOException: 远程主机强迫关闭了一个现有的连接。}}/*** pdf预览**@param configurer   freemarker配置*@param templateName freemarker模板名称(带后缀.ftl)*@param listVars     模板参数集*@param response     HttpServletResponse*/public static void preview(FreeMarkerConfigurer configurer, String templateName, List<Map<String, Object>> listVars, HttpServletResponse response) {try (ServletOutputStream out = response.getOutputStream()) {generateAll(configurer, templateName, out, listVars);out.flush();} catch (Exception e) {LOGGER.error(e.getMessage(), e);}}
}

获取内容

package com.bamboo.markdown.paper.controller;import com.bamboo.markdown.paper.common.FtlTransPdfUtils;
import com.bamboo.markdown.paper.entity.vo.ArticleView;
import com.bamboo.markdown.paper.repository.ArticleRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
import org.xml.sax.SAXException;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;/*** Created by admin on 2018/6/18.*/
@Controller
@RequestMapping(value = "/pdf")
public class PdfController {@Autowiredprivate FreeMarkerConfigurer configurer;@Autowiredprivate ArticleRepository articleRepository;/*** pdf预览** @param request  HttpServletRequest* @param response HttpServletResponse*/@RequestMapping(value = "/preview/{id}", method = RequestMethod.GET)public void preview(HttpServletRequest request, HttpServletResponse response, @PathVariable Integer id) throws IOException, SAXException {ArticleView articleView = new ArticleView(articleRepository.findById(id));// 构造freemarker模板引擎参数,listVars.size()个数对应pdf页数List<Map<String, Object>> listVars = new ArrayList<>();Map<String, Object> variables = new HashMap<>();variables.put("title", articleView.getTitle());//补充修正String htmlContent = articleView.getHtmlMaterial().replace("<br>", "<br/>");//匹配img标签的正则表达式String regxpForImgTag = "<img\\s[^>]+>";Pattern pattern = Pattern.compile(regxpForImgTag);Matcher matcher = pattern.matcher(htmlContent);StringBuffer sbr = new StringBuffer();while (matcher.find()) {String temp = matcher.group();matcher.appendReplacement(sbr, temp.replace(">", " />"));}matcher.appendTail(sbr);String htmlMaterial = sbr.toString();String regxpForImgTag2 = "<pre><code\\s[^>]+>";Pattern pattern2 = Pattern.compile(regxpForImgTag2);Matcher matcher2 = pattern2.matcher(htmlMaterial);StringBuffer sbr2 = new StringBuffer();while (matcher2.find()) {String temp2 = matcher2.group();matcher2.appendReplacement(sbr2, temp2.replace("<pre><code class=\"lang-java\">"," <pre class=\"prettyprint linenums prettyprinted\" style=\"\"><code class=\"lang-java\">"));}matcher2.appendTail(sbr2);variables.put("content", sbr2.toString());variables.put("len", htmlMaterial.length());listVars.add(variables);//FtlTransPdfUtils.preview(configurer, "pdf/pdfPage.ftl", listVars, response);}/*** pdf下载** @param request  HttpServletRequest* @param response HttpServletResponse*/@RequestMapping(value = "/download/{id}", method = RequestMethod.GET)public void download(HttpServletRequest request, HttpServletResponse response, @PathVariable Integer id) {ArticleView articleView = new ArticleView(articleRepository.findById(id));List<Map<String, Object>> listVars = new ArrayList<>();Map<String, Object> variables = new HashMap<>();variables.put("title", articleView.getTitle());//补充修正String htmlContent = articleView.getHtmlMaterial().replace("<br>", "<br/>");//匹配img标签的正则表达式String regxpForImgTag = "<img\\s[^>]+>";Pattern pattern = Pattern.compile(regxpForImgTag);Matcher matcher = pattern.matcher(htmlContent);StringBuffer sbr = new StringBuffer();while (matcher.find()) {String temp = matcher.group();matcher.appendReplacement(sbr, temp.replace(">", " />"));}matcher.appendTail(sbr);String htmlMaterial = sbr.toString();String regxpForImgTag2 = "<pre><code\\s[^>]+>";Pattern pattern2 = Pattern.compile(regxpForImgTag2);Matcher matcher2 = pattern2.matcher(htmlMaterial);StringBuffer sbr2 = new StringBuffer();while (matcher2.find()) {String temp2 = matcher2.group();matcher2.appendReplacement(sbr2, temp2.replace("<pre><code class=\"lang-java\">"," <pre class=\"prettyprint linenums prettyprinted\" style=\"\"><code class=\"lang-java\">"));}matcher2.appendTail(sbr2);variables.put("content", sbr2.toString());variables.put("len", htmlMaterial.length());listVars.add(variables);FtlTransPdfUtils.download(configurer, "pdf/pdfPage.ftl", listVars, response, articleView.getTitle() + ".pdf");}
}

资源文件图,字体在github那个项目获得

flying-saucer-pdf预览及下载相关推荐

  1. PDF 预览和下载你是怎么实现的?

    在开发过程中要求对 PDF 类型的发票提供 预览 和 下载 功能,**PDF** 类型文件的来源又包括 H5 移动端 和 **PC 端**,而针对这两个不同端的处理会有些许不同,下文会有所提及. 针对 ...

  2. 移动端和PC端的pdf预览与下载

    34.移动端和PC端的pdf的预览与下载 1.预览 需求:在手机端实现pdf的文件与下载,主要是zlb_app中 实现过程:在研究了vue-pdf.pdfjs.pdfh5之后,选择了vue-pdf-s ...

  3. Springboot实现PDF预览、下载、读取

    背景:项目中实现pdf文件的预览以及下载 环境:jdk1.8.SpringBoot2.0 PDF.js下载地址将下载的源码拷入项目中 修改viewer.js: 将defaultUrl: {value: ...

  4. vue 后台返回的文件流进行预览_vue项目-pdf预览和下载,后台返回文件流形式

    背景:正好最近碰到了这种需求,记录下来,方便以后查看. 后端返回的文件流数据如下图所示: 后台返回数据.png 一.pdf的预览 一开始的时候百度了很多方法,有建议用pdfJs插件的,有iframe嵌 ...

  5. 链接的图片转base64,字符串转流pdf预览-zip下载

    getBase64Image(src, outputFormat) {let img = new Image();img.setAttribute("crossOrigin", & ...

  6. php+预览和下载pdf文件,vue实现在线预览pdf文件和下载(pdf.js)

    最近做项目遇到在线预览和下载pdf文件,试了多种pdf插件,例如jquery.media.js(ie无法直接浏览) 最后选择了pdf.js插件(兼容ie10及以上.谷歌.安卓,苹果) 强烈推荐改插件, ...

  7. 前端实现pdf文件的在线预览与下载

    前言 在项目中我们经常会出现各种各样的法律文件.免责说明等文件需要用户阅读,很多文件除了阅读外还要支持用户下载.为了快速开发,一些变动不大的文件,或者是项目中不想开发富文本的时候我们可以选择直接使用p ...

  8. Nginx配置文件目录实现pdf文件预览及下载

    默认情况下,通过nginx服务器来访问pdf文件,在浏览器上是会直接打开该pdf文件呈现内容的.如果想要访问pdf文件时,实现下载文件的效果,则需要在nginx服务端做一些配置. 以下配置只能下载 n ...

  9. vue 项目中实现pdf预览 pdf打印 pdf下载

    在Vue项目中实现PDF预览.打印和下载可以通过以下步骤来实现: 安装pdf.js pdf.js是一个JavaScript库,可以用于在Web上渲染PDF文件. 可以使用npm安装pdf.js,命令如 ...

  10. VUE 前端PDF分页预览、下载

    一.安装PDF插件依赖 // pdf预览 npm install vue-pdf --save// pdf下载 npm install downloadjs 二.完整示例 <template&g ...

最新文章

  1. Linux别名的创建删除【alias】和【unalias】
  2. 测试CPU品牌和当前工作频率
  3. 报告显示:2018年北京人工智能相关产业达1500亿元
  4. 2.7 负采样-深度学习第五课《序列模型》-Stanford吴恩达教授
  5. 关于MVC框架和spring
  6. 从Uboot到Linux技术
  7. UE4学习-材质快捷键及材质帮助手册
  8. mysql5.7.17解压版安装_Windows中 MySQL5.7.17解压版安装步骤
  9. 代码实现——MapReduce实现Hadoop序列化
  10. 粗看ES6之JSON
  11. 20190226work
  12. Python 最大公约数的欧几里得算法及Stein算法
  13. ASP.NET 缓存(10)
  14. 计算机硬盘模式,Win7系统将电脑BIOS硬盘模式修改为ahci模式的具体方法
  15. 【100+ python基础入门-37】Python可变集合和不可变集合的构造方法和注意事项
  16. 人工智能会使人类整体性地沦为彻底的“无用阶级”吗?
  17. 尝鲜体验win11,附赠win11镜像下载地址
  18. 大疆2019校招FPGA笔试总结
  19. 试算平衡表两种方法比较
  20. 2.19 校验码的概念

热门文章

  1. FrameBuffer操作
  2. 如何控制鼠标和键盘的操作
  3. 安卓u盘格式化工具apk_华为智慧屏U盘安装APP分享
  4. LwIP应用笔记(二):无操作系统支持下的RAW API移植
  5. Datawhale 202210 Excel | 第九、十章 Excel数据可视化
  6. Android 暗黑模式适配
  7. ocm认证年薪多少_华为“天才少年”张霁:本硕“双非”,凭啥斩获最高年薪201万...
  8. APP 分析 随手记
  9. OSChina 周日乱弹 ——我对象整天在家打游戏,怎么办?
  10. docker容器内开启22 ssh_细述docker容器中创建SSH服务镜像