最近公司要求做一个导出PDF报表的功能。由于时间比较紧张,而且导出的内容暂时为一个报表而已,所以我采用了flying saucer+freemaker来做。

flying sauce源码:https://github.com/flyingsaucerproject/flyingsaucer

至于为什么选择flying saucer,详细请看:https://blog.csdn.net/qq_36961530/article/details/72628028

结合方案对比,详细请看:https://blog.csdn.net/blackmonkey/article/details/75096084

flying saucer是基于itext的,其最大的优势,是对css2.1的支持,页面渲染效果很好~特别是在做html转PDF时。话不多说,你看!

1.jar引入

Gradle项目:

compile ('org.xhtmlrenderer:flying-saucer-pdf:9.0.8') 

Maven项目:

<dependency><groupId>org.xhtmlrenderer</groupId><artifactId>flying-saucer-pdf</artifactId><version>9.0.8</version>
</dependency>

具体的PDFUtils代码下次补上~~~~~~~~~~~~~~~~~~~~~~~~~~~~~(华丽分割线)~~~~~~~~~~~~~~~~~~~~~~~~~~~

***************************************坑点大全******************************************

1.中文支持问题

因为这个框架是外国人写的,中文对于外国人太过复杂,特别是支持语言包的编写上。所以,所有的flying-saucer包均不支持中文。

第一步:虽然不支持中文,但是外国人给我们一个字体类:BaseFont类。只要在这个类中,加入你想要支持的字体文件(.afm、.pfm、.ttf、.otf、.ttc均支持哦,有兴趣的同学可以去研究下这个BaseFont源码,欢迎评论区留言~),具体代码如下:

ITextRenderer render = new ITextRenderer();
render.getFontResolver().addFont(fontPath, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
/*
参数说明:
fontPath字体的路径
BaseFont.IDENTITY_H 字体水平书写 IDENTITY_V 为垂直书写
BaseFont.NOT_EMBEDDED 字体不需要嵌入
BaseFont Api详细:https://www.coderanch.com/how-to/javadoc/itext-2.1.7/com/lowagi/text/pdf/BaseFont.html
*/

第二步:在你的html上加上字体!html上加上字体!html上加上字体!重要的事情说三遍!!!

<body style = "font-family: SimHei; font-size:small;"></body>

2.中文换行问题

org.xhtmlrenderer:flying-saucer-pdf这个jar包在9.0.1版本之前都是不支持中文换行的。(解决方案:需要对Jar包中的Breaker.class进行修改,很多国内大佬都有修改方案,详细请看:https://blog.csdn.net/conan1210/article/details/50750849)

附上修改主要代码:

private static boolean isChinese(char c){Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);  if(ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS || ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A || ub == Character.UnicodeBlock.GENERAL_PUNCTUATION || ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION || ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS){return true;}return false;
}private static int getStrRight(String s, int left){if(left >= s.length()) return -1;char[] ch = s.toCharArray();for(int i = left; i < ch.length; i++){ if(isChinese(ch[i]) || ' ' == ch[i]){return i==0?i+1:i; } }
return -1;
}

2.1 这样修改源码只是对中文做了一个简单的换行处理,并不能自动识别标点比如逗号或者表单数据中,句段的合理换行。所以,为了能让你的PDF好看点,强烈不推荐使用9.0.1及其之前的版本!!!

3.路径问题(这个绝对是最最最最坑的,差点让我放弃flying saucer)

3.1 首先,让我们来研究下:不同系统的路径问题。(主要是:windows和linux)

就拿字体文件路径举例:比如我需要引入项目中 resources/fonts/simhei.ttf

在windows系统上:

不管你用ClassLoaber.getResource()或System.getProperty("user.dir")或者getServletContext().getRealPath("/")。。。只要能获取项目的绝对路径都OK。输出的路径应为这样的形式: /E:/MyWorkspace/项目名/xxx/classes/

String fontPath = Thread.currentThread().getContextClassLoader(). getResource(font).
getPath();
//font为:fonts/simhei.ttf
render.getFontResolver().addFont(fontPath, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
在linux系统上:

首先,你要明白,在linux下file:/无法被识别,运用file:///来声明根目录 详细请看:https://blog.csdn.net/u010515155/article/details/76186728

解决方案:建议把simhei.ttf字体文件放在在linux系统中 : /user/share/font/simhei.ttf

render.getFontResolver().addFont(fontPath, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
//fontPath为: "/usr/share/simhei.ttf"

3.2 然后,我们再来研究下要导出的html中有图片,图片的路径

图片的路径也必须是绝对路径才可以识别哦~代码如下:

render.getSharedContext().setBaseURL("file://"+Thread.currentThread().getContextClassLoader().getResource(imagePath).getPath());//imagePath 为:图片在html中使用的路径
//这里路径eg : file:///E:...的路径,在windows和linux中均可以识别。

3.3 最后,这里还有个大坑,就是项目的所需资源打成外jar包时,路径访问的问题,是不支持new File()读取文件的!!!

我在使用getFontResolver().addFont()这个方法时,由于生产环境的项目是打成jar包的形式,居然无法识别路径,无法指定到字体文件或图片。经过千辛万苦,不断读源码,终于找到原因:https://blog.csdn.net/b_h_l/article/details/7767829

你猜的不错,addFont()方法就不支持从Jar包中获取资源文件!!!

其实,render.getFontResolver().addFont()这个方法的底层是BaseFont.createFont()实现的,源码如下:

然后我们再来看看BaseFont的createFont()的底层实现:(源码一时找不到了,找到了会补充进来~)

但是,这个方法是通过File f = new File(path)实现的。所以无法从jar包获取资源

针对这个问题,我个人提出了三种解决方案:

1.使用原生的itext5来写html文件,其中可以利用中文支持包iText-asian来引入字体,从而解决中文问题。

BaseFont bfChinese = BaseFont.createFont( "STSongStd-Light" ,"UniGB-UCS2-H",BaseFont.NOT_EMBEDDED);

但需要注意:flying sauce是基于iText2.1.7,低版本的iText-asian包和iText2.1.7会有包名冲突。需要改包名。

详细请看:https://blog.csdn.net/lvqfly/article/details/50681539

2.jar包中的资源是可以被读取的,比如说利用流的形式。思路为:先从Jar包中获取资源文件,写入存到项目文件中,然后通过项目文件路径获取资源。

3.在flying sauce中,字体处理器ITextFontResolver的父类FontResolver,其还有另一个实现类:AWTFontResolver。尝试继承这个类并重写以字节流的形式读取路径文件,再通过render.getSharedContext().setFontResolver(),强制转换一波应该可以实现。目前还在实验中~有兴趣的同学可以加我QQ(714635093)一起讨论~~~

flying saucer做导PDF踩过的坑~相关推荐

  1. iText和flying saucer结合生成pdf的技术

    原博文地址 http://blog.csdn.net/shanliangliuxing/article/details/6833471 下面是我自己利用flying saucer技术生成pdf文档的实 ...

  2. iTextRenderer(Flying Saucer) HTML转PDF

    iTextRenderer(Flying Saucer) HTML转PDF iTextRenderer 在依赖 iText 的基础上,单独实现了HTML渲染PDF,基本上能实现 CSS 2.1的整体性 ...

  3. 用vant框架做H5时踩过的坑(下拉刷新、上拉加载等)

    用vant框架做H5时踩过的坑 1. 页面在手机端不能上下滑动,在PC端浏览器正常滑动 说明:在设置了overflow:auto;属性的前提下,H5页面在PC端浏览器里展示可以上下滑动,在ios上可正 ...

  4. itext转html为pdf 锚点,flying saucer html转pdf经验分享

    对比了很多生成pdf的方案,最终还是决定使用flying saucer,网上能搜出N多相关文章,但是照着做了会出现各种问题,还是得自己一点点摸索,前后花了两天时间才达到自己的目标,下面把过程中的经验总 ...

  5. UE4 虚幻引擎 Montage蒙太奇/动画蓝图状态机 踩过的坑记录

    惯例先说两句 实在惭愧,和朋友一起做UE4从10月份就说好了,结果依旧拖到了寒假,然而毕设又来了. 第一关的锅我背了三个月还没做完,直到疫情被困在家必须好好干一把了(加油) 以下是在最近做一个简单的道 ...

  6. Flying Saucer生成pdf报表

    使用Flying Saucer生成pdf报表: 1.首先看一下Flying Saucer的官方介绍: https://github.com/flyingsaucerproject/flyingsauc ...

  7. 使用flying saucer将html文件转成PDF

    使用flying saucer生成PDF文件之前,先要使用freemarker生成html文件,然后将html文件转成pdf.生成html文件的东东网上一搜一大堆,大家找找就成. 当然"使用 ...

  8. flyingsaucer转换多个html,Flying Saucer实现html转pdf(一些有关问题,持续更新)

    Flying Saucer实现html转pdf(一些问题,持续更新) Flying Saucer实现html转pdf(及一些问题,持续更新) 关于FlyingSaucer的使用官网上有详细的介绍. 官 ...

  9. flyingsaucer转换多个html,用 flying saucer 生成pdf文件 Css及html的问题

    我用  flying saucer  生成PDF文件,因为要生成文章,而文章是由tinymce发布的.可能有些文章发布出去后格式有问题,比如说标签不规范,有的没有闭合. 这样 flying sauce ...

最新文章

  1. icinga安装介绍,监控软件
  2. openJDK之lambda——List的forEach如何实现的
  3. Oracle to_char格式化函数
  4. python心得体会-终于懂得python基础学习心得
  5. Eclipse中server启动超时的解决方法
  6. OpenCV示例学习(七):离散傅里变换(DFT)算子:getOptimalDFTSize(),copyMakeBorder(),magnitude(),log(),normalize()
  7. SQL Server 2012之初次安装
  8. Docker教程(二) Docker环境安装
  9. Berkeley DB Java Edition
  10. 关于git和SVN的介绍和区别
  11. css重新认识(2)
  12. 宁波财经学院计算机原理题库,计算机原理题库(整合版)
  13. Python 招聘信息爬取及可视化
  14. 如何利用Vue实现页面的局部刷新
  15. ECMAScript6语法检查规范错误信息说明
  16. php sequelize,关于javascript:eggjs-sequelize-的常用方法总结
  17. Xshell安装报错1605
  18. [模型]多目标规划模型
  19. 【以太网数据包】OICQ数据包(QQ)
  20. 算法导论答案 思考题15-1 双欧几里德旅行商问题

热门文章

  1. axure 元件_Axure流程图制作
  2. HTTP协议详解你确定不看吗
  3. 联通混改BATJ悉数入局,拿出数百亿的百度们有什么阳谋?
  4. 交换机的Zoning技术
  5. amCharts 报表(转)
  6. stm32将flash虚拟成U盘来下载程序
  7. 劳务派遣有五险一金吗?
  8. 面试被问离职原因,别乱说
  9. 杨承润:世界首席创业家导师杨承润,创业16年,杨承润和他的《慧眼经营思维》
  10. 根据性别自动切换用户图标——DAY4