`
songlixiao
  • 浏览: 23234 次
  • 性别: Icon_minigender_1
  • 来自: 青岛
社区版块
存档分类
最新评论

使用flyingsaucer将网页转换为pdf之中文问题彻底解决

    博客分类:
  • java
阅读更多

    前几天遇到个导出pdf 的需求,在网络上查找了一下java导出pdf 的方案.多数人推荐使用iText,研究了一下,感觉直接写pdf的方法太笨,可维护性差,一旦pdf格式要变化改起来很费劲.还有一个方案,可以先预先定义一个pdf作为模板文件,然后用业务数据进行填空.是个不错的方案,只可惜不适合我的需求.需求中有些行是动态加行的,这个方案无法实现.后来发现有可以将网页直接转成pdf 的开源包flyingsaucer (中文名:灰碟),逐将注意力转移到这上面,发现是个不错的选择.只要写网页就可以了,而且pdf格式变化维护起来也方便,代码也会比较干净.只是它对中文支持 的不好,但这不是无法解决的.下面就来说说这个flyingsaucer .

    Flyingsaucer 使用iText2.0.8作为其pdf输出的基础工具,另外增加了解析html/xml并形成pdf式排版的功能.最重要的它还支持css样式表.组合这些能力后,它就可以将网页变成pdf了.但是,它也有他的问题.大家知道iText的版本现在已经升级为5.0以上了,而flyingsaucer 却依然沿用2.0.8的版本.为什么呢? 因为这个灰碟貌似自2007年就已经停止维护了,最终版本flyingsaucer-R8.也就是说这是个几年前的工具包,至于新的替代此功能的包又在哪里?我没有找到,倒是有个功能相似但是收费的,不知道是不是它的成长版.这是题外话我们不研究.只看这个flyingsaucer -R8这个版本能否满足我们的基本要求吧.
    在使用过程中发现flyingsaucer -R8对导出pdf的网页有一些要求.
    1.  所有的标签必须都闭合.
    2.  网页开头引入的DTD必须与网页体中使用的标签一致.
    3.  部分不太常用的html标签貌似不认.比如<u>.
    因为flyingsaucer 解析html文档是遵照xml标准来的,所以这个网页写起来不能像我们平时的网页那么随意.xml该有的规则都要遵守.这个要求并不高我们可以做到,而且试了下导出的pdf文档没啥问题,因此我们还是可以使用它来满足我们的需求.(至于,这个工具包怎么用,这里有不多说了,google一下一大片.这里只写目前google不到的东西.)
    既然要用它不可回避的就会遇到其对中文支持 不好的问题.
    问题1:来源自渲染器输出时没有使用支持中文的字体.虽然我们看到iText有亚洲语言包iTextAsian.jar,但是仅仅引入此包并不能使我们的中文字符输出.以至于网上有个哥们写到:
    打开ITextOutputDevice这个类找到:
Java代码
cb.setFontAndSize(_font.getFontDescription().getFont(), _font.getSize2D() / _dotsPerPoint);   

 

改成:
Java代码
try {    
            cb.setFontAndSize(BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED), _font.getSize2D()/_dotsPerPoint);    
        } catch (Exception e) {    
        }   

 

    Ok,改了以后我们终于可以看到pdf里有中文了.但是别高兴的太早哦,问题并没有完全解决.如果一段标签中有且只有中文字符的时候,导出pdf后内容便会消失.比如<div>中文</div>,这样的代码将什么也输出不了,而<div>中文a</div>则会将标签内容全部输出.通过测试我们发现,纯中文是无法输出的,但是加上一点点英文、数字或符号就可以输出了.有同学可能要说我们把纯中文后面加上空格不就行了?我只能说很不幸,加空格是不管用的.如果你的页面上纯中文的地方可以随便让你加字母/数字/符号,那可以不必往下看了.但是我觉得大多数的人恐怕不会这么干的,即使我们想客户也不让啊.那就要解决这个问题.
开源的东西有个好处,可以看源代码.从源码中我发现是字体的问题,于是乎,google一下,找到以下方案:
在导出的代码里加入这两句引入字体
Java代码
 
ITextFontResolver fontResolver = renderer.getFontResolver();       
fontResolver.addFont("C:/WINDOWS/Fonts/ARIALUNI.TTF", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);   
  
于是我照做了.杯具的是情况没有任何好转.即使有好转这个绝对路径的字体引入方式也很让人不舒服吧.所以这个不是我们想要的解决方案.
    Google不到只能继续从代码里找办法了.通过跟深入的研究代码,发现问题根源所在.输出PDF时在计算字符宽度的时候,对中文字符计算出的宽度居然是0.这也就能解释为什么纯中文字符串输出后会看不到了,因为字符总体的宽度被计算为0也就失去了被输出的机会,而加上一点非中文字符的则至少会有一点宽度,即获得了输出的机会,即使实际宽度比计算的宽度要宽也是可以输出的.
    于是修改BaseFont中的getWidth(String text)方法
Java代码
if (char1 < 128 || (char1 >= 160 && char1 <= 255))    
    total += widths[char1];    
else   
    total += widths[PdfEncodings.winansi.get(char1)];   

 

这几行改为:

if (char1 < 128 || (char1 >= 160 && char1 <= 255))    
    total += widths[char1];    
else if ((char1 >= 19968) && (char1 <= 40869)) // 如果是中文字符加宽度500    
    total += 500;    
else   
    total += widths[PdfEncodings.winansi.get(char1)];   
 

    再次测试,通过.至此,使用flyingsaucer网页导出成pdf中文问题 总算解决了.可是总觉得这个解决的方法有点不太正宗,因为修改了父类嘛.但又没有找到其他正宗的解决方案,只能先这样解决一下了.发出此文,只当抛砖引玉,如果有哪位高人有更好的解决方案请不吝赐教啊.

    附件提供修改了的flyingsaucer -R8的两个jar包: core-renderer.jar和iText2.0.8.jar另有一个iText亚洲语言包.

    原文:http://www.oecp.cn/hi/slx/blog/1857

 

提供该文档的机构为 百洋软件研究实验室 ,更多的博客文章可以到 百洋软件研究实验室博客 查看。该文档附件欢迎各位转载,但是在没有获得文章作者许可之前,不得对文章内容或者版权信息进行更改,版权归 百洋软件研究实验室 所有,仅此声明。

4
1
分享到:
评论
5 楼 wangyangzhizhou 2011-12-01  
多谢楼主,这个问题困扰了我两天了,都快崩溃了,还好看到楼主的文章!不胜感激!!
4 楼 songlixiao 2010-10-11  
hunnuxiaobo 写道
引用
else if ((char1 >= 19968) && (char1 <= 40869)) // 如果是中文字符加宽度500      

为什么加500?楼主能详细解释一下么?


嘿嘿.这个数加的比较随意.好像英文单字母在源代码里是按照400多计算的,记不太清了.
这个地方其实加多少都行,甚至只加1都可以.造成中文不显示的原因是,中文在这里被认为没有宽度,而不进行输出.只要有一点点宽度,当中文字符输出的时候,就可以写上了,并且不会受宽度限制,会把那一点点宽度撑开.
3 楼 hunnuxiaobo 2010-09-30  
引用
else if ((char1 >= 19968) && (char1 <= 40869)) // 如果是中文字符加宽度500      

为什么加500?楼主能详细解释一下么?
2 楼 songlixiao 2010-07-06  
mogui258 写道
呵呵,不标准的 html 网页 能转换吗?上次困扰了好久,还是用itext 了!

不标准的貌似不行哎.我也试过了,最后只好重新写了一个标准的页面,专门用来转换.
1 楼 mogui258 2010-07-06  
呵呵,不标准的 html 网页 能转换吗?上次困扰了好久,还是用itext 了!

相关推荐

    flyingsaucer转html为PDF(中文可用)

    以下是如何使用`Flyingsaucer`将包含中文的HTML转换为PDF的步骤: 1. **添加依赖**:首先,你需要在项目中引入`Flyingsaucer`和`iText`的依赖。对于Java项目,这通常是在`pom.xml`(Maven)或`build.gradle`...

    flying-saucer-pdf 生成pdf解决图片问题 解决中文问题

    本文将详细探讨`flying-saucer-pdf`如何解决图片问题以及中文显示问题。 首先,让我们关注一下图片问题。在HTML到PDF的转换过程中,图片的处理是个常见挑战。`flying-saucer-pdf` 支持多种图片格式,如JPEG、PNG、...

    Flying Saucer实现html转pdf(一些问题,持续更新)

    本文将深入探讨如何使用Flying Saucer实现HTML到PDF的转换,并解决可能遇到的一些问题。 首先,让我们了解Flying Saucer的基本原理。它基于开源的Web浏览器引擎Itext,可以解析HTML、CSS,并将其渲染为PDF。 Flying...

    flying saucer的中文不显示问题(修改源码后重新打的jar包)

    将这个新jar包集成到你的项目中,可以确保在使用Flying Saucer将网页转换为PDF时,中文内容能够正确显示。 总的来说,解决"Flying Saucer的中文不显示问题"是一个涉及字符编码配置和字体资源管理的过程。通过修改...

    SpringBoot集成Freemarker+FlyingSaucer实现pdf在线预览.pdf

    4. 使用FlyingSaucer将HTML文档转换为PDF文档。 六、技术点总结 本方案中涉及到的技术点包括: * Freemarker模板引擎:用于生成HTML模板。 * FlyingSaucer PDF生成:用于将HTML文档转换为PDF文档。 * SpringBoot...

    用flying saucer将html生成pdf的例子

    在本例子中,freemarker可能被用来创建HTML模板,这些模板可以包含动态内容,如用户数据或者其他服务器端计算的结果,然后再由flying saucer转换为PDF。 使用这三者结合的方式生成HTML到PDF的过程大致如下: 1. **...

    flying-saucer生成pdf

    flying-saucer是一个非常实用的开源库,它允许开发者通过HTML和CSS将网页内容转换为PDF格式,从而解决了多种问题。以下是对这个主题的详细解释。 1. **图片显示问题**: 在使用flying-saucer生成PDF时,可能会遇到...

    flyingsaucer html转pdf demo

    下面是一个简单的使用Flyingsaucer将HTML转换为PDF的步骤: 1. **引入依赖**:首先,在你的项目中添加Flyingsaucer相关的依赖库。对于Java Maven项目,可以在pom.xml文件中添加以下依赖: ```xml &lt;groupId&gt;org....

    flying-saucer-pdf-9.0.9转pdf相关包

    标题中的“flying-saucer-pdf-9.0.9转pdf相关包”指的是使用`flying-saucer`库的特定版本9.0.9来将HTML转换为PDF的工具集。 1. **flying-saucer-pdf-9.0.9.jar**:这是`flying-saucer`的核心组件,负责将HTML渲染成...

    flyingsaucer指导文档

    - **应用场景**: 常用于将网页内容、报表数据或其他结构化的XML数据转换成易于阅读的PDF文档,或者将网页截图保存为图像文件。 ##### 1.2 FlyingSaucer的功能 - **支持的输入格式**: 主要接受XML文件作为输入,...

    Flying Saucer ,简单实用的pdf转换api

    Flying Saucer是一个开源Java库,专门用于将HTML文档转换为PDF格式。这个API因其易于使用和功能强大而受到开发者的欢迎。在本文中,我们将深入探讨Flying Saucer的核心概念、工作原理以及如何在实际项目中应用它。 ...

    flying-saucer-coreR 解决PDF中文没对齐问题

    flying-saucer-coreR-9.0.7 中修改Breaker类,解决PDF中文没有对齐问题。

    基于iText和flying saucer结合freemark生成pdf 范例

    基于iText和flying saucer结合freemark生成pdf 范例 1. 使用maven构建,不含jar包,可以自行使用maven下载依赖包, 2. 使用前需要将C:/Windows/Fonts/ARIALUNI.TTF 复制到doc-render/src/test/resources/config/fonts...

    利用flying saucer 生成Pdf的例子

    总之,通过Flying Saucer和IText,我们可以轻松地将HTML内容转换为高质量的PDF文档,同时解决中文显示问题。这个过程涉及字体配置、字符集设定、CSS样式以及编码转换等多个方面。在实际开发中,了解和掌握这些知识点...

    flyingSaucer.jar

    `flyingSaucer.jar` 是一个用于将HTML文档转换为PDF格式的开源库,它在处理中文内容时能够有效避免乱码问题。这个库在IT领域,特别是文档处理和自动化报告生成方面有着广泛的应用。下面我们将深入探讨 `flyingSaucer...

    Flying Saucer 支持中文宋体win,Linux,直接使用

    Flying Saucer 支持中文宋体win,Linux; Css 页面字体修改为 font-family:STSong; 就可以了,具体

    Flying-Saucer使用HTML或者FTL(Freemarker模板)生成PDF

    Flying-Saucer通过html生成pdf。。。项目中已经附带了jar包,放到项目中就可以运行了...亲测了,解决了中文不显示或者样式的问题,感觉蛮实用的。网上找了很久和下载其他资源用了好多积分,如果有需要的就下载吧!!!

    flyingsaucer-R8.zip

    Freemarker是一个强大的模板引擎,可以方便地将数据和模板结合,生成动态HTML,然后再由Flyingsaucer转换为PDF。 总结起来,Flyingsaucer和iText的组合提供了一种高效且灵活的方法来生成PDF,尤其适合需要从HTML...

Global site tag (gtag.js) - Google Analytics