flying-saucer-pdf预览及下载

2024-05-06 23:08
文章标签 pdf 下载 预览 flying saucer

本文主要是介绍flying-saucer-pdf预览及下载,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

使用这个库的初衷

找阿里编程规范的时候在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预览及下载的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/965643

相关文章

基于Python实现一个PDF特殊字体提取工具

《基于Python实现一个PDF特殊字体提取工具》在PDF文档处理场景中,我们常常需要针对特定格式的文本内容进行提取分析,本文介绍的PDF特殊字体提取器是一款基于Python开发的桌面应用程序感兴趣的... 目录一、应用背景与功能概述二、技术架构与核心组件2.1 技术选型2.2 系统架构三、核心功能实现解析

基于Python开发PDF转Doc格式小程序

《基于Python开发PDF转Doc格式小程序》这篇文章主要为大家详细介绍了如何基于Python开发PDF转Doc格式小程序,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 用python实现PDF转Doc格式小程序以下是一个使用Python实现PDF转DOC格式的GUI程序,采用T

Python如何快速下载依赖

《Python如何快速下载依赖》本文介绍了四种在Python中快速下载依赖的方法,包括使用国内镜像源、开启pip并发下载功能、使用pipreqs批量下载项目依赖以及使用conda管理依赖,通过这些方法... 目录python快速下载依赖1. 使用国内镜像源临时使用镜像源永久配置镜像源2. 使用 pip 的并

jdk21下载、安装详细教程(Windows、Linux、macOS)

《jdk21下载、安装详细教程(Windows、Linux、macOS)》本文介绍了OpenJDK21的下载地址和安装步骤,包括Windows、Linux和macOS平台,下载后解压并设置环境变量,最... 目录1、官网2、下载openjdk3、安装4、验证1、官网官网地址:OpenJDK下载地址:Ar

使用Python创建一个能够筛选文件的PDF合并工具

《使用Python创建一个能够筛选文件的PDF合并工具》这篇文章主要为大家详细介绍了如何使用Python创建一个能够筛选文件的PDF合并工具,文中的示例代码讲解详细,感兴趣的小伙伴可以了解下... 目录背景主要功能全部代码代码解析1. 初始化 wx.Frame 窗口2. 创建工具栏3. 创建布局和界面控件4

Python进行PDF文件拆分的示例详解

《Python进行PDF文件拆分的示例详解》在日常生活中,我们常常会遇到大型的PDF文件,难以发送,将PDF拆分成多个小文件是一个实用的解决方案,下面我们就来看看如何使用Python实现PDF文件拆分... 目录使用工具将PDF按页数拆分将PDF的每一页拆分为单独的文件将PDF按指定页数拆分根据页码范围拆分

Android开发中gradle下载缓慢的问题级解决方法

《Android开发中gradle下载缓慢的问题级解决方法》本文介绍了解决Android开发中Gradle下载缓慢问题的几种方法,本文给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧... 目录一、网络环境优化二、Gradle版本与配置优化三、其他优化措施针对android开发中Gradle下载缓慢的问

python 3.8 的anaconda下载方法

《python3.8的anaconda下载方法》本文详细介绍了如何下载和安装带有Python3.8的Anaconda发行版,包括Anaconda简介、下载步骤、安装指南以及验证安装结果,此外,还介... 目录python3.8 版本的 Anaconda 下载与安装指南一、Anaconda 简介二、下载 An

Python如何实现PDF隐私信息检测

《Python如何实现PDF隐私信息检测》随着越来越多的个人信息以电子形式存储和传输,确保这些信息的安全至关重要,本文将介绍如何使用Python检测PDF文件中的隐私信息,需要的可以参考下... 目录项目背景技术栈代码解析功能说明运行结php果在当今,数据隐私保护变得尤为重要。随着越来越多的个人信息以电子形

Java下载文件中文文件名乱码的解决方案(文件名包含很多%)

《Java下载文件中文文件名乱码的解决方案(文件名包含很多%)》Java下载文件时,文件名中文乱码问题通常是由于编码不正确导致的,使用`URLEncoder.encode(filepath,UTF-8... 目录Java下载文件中文文件名乱码问题一般情况下,大家都是这样为了解决这个问题最终解决总结Java下