转载请注明出处 https://www.cnblogs.com/majianming/p/9539376.html

项目中需要对订单生成pdf文件,在第一版本其实已经有了比较满意的pdf文档,但是还是存在问题的,主要是itext的css支持能力实在是太差,测试过程中发现margin都不支持,和我对接pdf的html模板的伙伴也是一直在改,凭着不想一直被打的希望,终于找到了下面好一点的方案。总的来说,就是加了itextrender这个支持常见的css2.1的封装。

首选介绍一下这次使用的环境设置

  1. spring boot 2.0
  2. itext 5.5.13
  3. xmlworker 5.5.13
  4. itext-asin asian 5.2.0
  5. flying-saucer-pdf-itext5 9.1.12

在maven pom文件添加

    <!-- https://mvnrepository.com/artifact/com.itextpdf/itextpdf -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.13</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.itextpdf/itext-asian -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.itextpdf.tool/xmlworker -->
<dependency>
<groupId>com.itextpdf.tool</groupId>
<artifactId>xmlworker</artifactId>
<version>5.5.13</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.xhtmlrenderer/flying-saucer-pdf-itext5 -->
<dependency>
<groupId>org.xhtmlrenderer</groupId>
<artifactId>flying-saucer-pdf-itext5</artifactId>
<version>9.1.12</version>
</dependency>

在代码中默认使用

    ITextRenderer iTextRenderer = new ITextRenderer();
iTextRenderer.setPDFVersion(PdfWriter.VERSION_1_7);
iTextRenderer.setDocumentFromString(html);//pdf的内容,有其他生成模式,方法名类似
iTextRenderer.layout();
try (ServletOutputStream outputStream = response.getOutputStream()) {
iTextRenderer.createPDF(outputStream);
} catch (IOException e) {
logger.error("输出pdf错误" + e.getMessage(), e);
} catch (DocumentException e) {
logger.error("生成pdf错误" + e.getMessage(), e);
}

好了,启动跑一下。中文文字一个都没有显示。按照之前的想法,那设置一下字体文件路径就好了吧,下面的借鉴于itext的com.itextpdf.text.FontFactoryImp#registerDirectories(), 用于向itextRender注册默认的字体路径,

    ITextRenderer iTextRenderer = new ITextRenderer();

    try {
ITextFontResolver fontResolver = iTextRenderer.getFontResolver();
String windir = System.getenv("windir");
String fileSeparator = System.getProperty("file.separator");
if (windir != null && fileSeparator != null) {
fontResolver.addFontDirectory(windir + fileSeparator + "fonts", BaseFont.NOT_EMBEDDED);
}
fontResolver.addFontDirectory("/usr/share/X11/fonts", BaseFont.EMBEDDED);
fontResolver.addFontDirectory("/usr/X/lib/X11/fonts", BaseFont.EMBEDDED);
fontResolver.addFontDirectory("/usr/openwin/lib/X11/fonts", BaseFont.EMBEDDED);
fontResolver.addFontDirectory("/usr/share/fonts", BaseFont.EMBEDDED);
fontResolver.addFontDirectory("/usr/X11R6/lib/X11/fonts", BaseFont.EMBEDDED);
fontResolver.addFontDirectory("/Library/Fonts", BaseFont.EMBEDDED);
fontResolver.addFontDirectory("/System/Library/Fonts", BaseFont.EMBEDDED);
} catch (IOException e) {
logger.error("字体路径读取异常", e);
//相关处理
return;
} catch (DocumentException e) {
logger.error("字体解析异常", e);
//相关处理
return;
}
iTextRenderer.setPDFVersion(PdfWriter.VERSION_1_7);
iTextRenderer.setDocumentFromString(html);
iTextRenderer.layout();
try (ServletOutputStream outputStream = response.getOutputStream()) {
iTextRenderer.createPDF(outputStream);
} catch (IOException e) {
logger.error("输出pdf错误" + e.getMessage(), e);
} catch (DocumentException e) {
logger.error("生成pdf错误" + e.getMessage(), e);
}

开心的运行起来,哈哈哈哈,要好了!

欸?还是一样,是我的问题?肯定是我的问题!那就继续看吧

看了许多的博客(忘记记录下来了,( ̄_, ̄ ))

看到许多添加字体文件的都是类似于 fontResolver.addFont("simsun.ttc",BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);,向解析器注册宋体字体;第三个参数是字体的嵌入行为,有嵌入和不嵌入两种。那第二个参数是什么,查看命名,也就是encoding,字体的编码方式,看看ITextFontResolver#addFontDirectory(Sting path,boolean embedded)这个方法中,调用了addFont(String path, boolean embedded),在这个方法中找到了问题的根源,上面调用fontResolver.addFontDirectory这个方法设置字体的默认编码为Cp1252,这个编码并不支持中文,也就很好的说明了为什么pdf上的中文字符都没有显示,那么我们设置为Identity-H,这个时候将上面的代码加以修改

首先修改默认的addFontDirectory方法

/**
* 因为默认设置的字体编码为西文,需要重写改为<code>BaseFont.IDENTITY_H</code>
*
* @param dir
* @param embedded
* @param fontResolver
* @throws DocumentException
* @throws IOException
*/
private void addFontDirectory(String dir, boolean embedded, ITextFontResolver fontResolver)
throws DocumentException, IOException {
File f = new File(dir);
if (f.isDirectory()) {
File[] files = f.listFiles((dir1, name) -> {
String lower = name.toLowerCase();
return lower.endsWith(".otf") || lower.endsWith(".ttf") || lower.endsWith(".ttc");
});
for (int i = 0; i < files.length; i++) {
fontResolver.addFont(files[i].getAbsolutePath(), BaseFont.IDENTITY_H, embedded);
}
}
}

所以生成的代码改为

    ITextRenderer iTextRenderer = new ITextRenderer();

    try {
ITextFontResolver fontResolver = iTextRenderer.getFontResolver();
String windir = System.getenv("windir");
String fileSeparator = System.getProperty("file.separator");
if (windir != null && fileSeparator != null) {
addFontDirectory(windir + fileSeparator + "fonts", BaseFont.NOT_EMBEDDED, fontResolver);
}
addFontDirectory("/usr/share/X11/fonts", BaseFont.EMBEDDED, fontResolver);
addFontDirectory("/usr/X/lib/X11/fonts", BaseFont.EMBEDDED, fontResolver);
addFontDirectory("/usr/openwin/lib/X11/fonts", BaseFont.EMBEDDED, fontResolver);
addFontDirectory("/usr/share/fonts", BaseFont.EMBEDDED, fontResolver);
addFontDirectory("/usr/X11R6/lib/X11/fonts", BaseFont.EMBEDDED, fontResolver);
addFontDirectory("/Library/Fonts", BaseFont.EMBEDDED, fontResolver);
addFontDirectory("/System/Library/Fonts", BaseFont.EMBEDDED, fontResolver);
} catch (IOException e) {
logger.error("字体路径读取异常", e);
//相关处理
return;
} catch (DocumentException e) {
logger.error("字体解析异常", e);
//相关处理
return;
}
iTextRenderer.setPDFVersion(PdfWriter.VERSION_1_7);
iTextRenderer.setDocumentFromString(html);
iTextRenderer.layout();
try (ServletOutputStream outputStream = response.getOutputStream()) {
iTextRenderer.createPDF(outputStream);
} catch (IOException e) {
logger.error("输出pdf错误" + e.getMessage(), e);
} catch (DocumentException e) {
logger.error("生成pdf错误" + e.getMessage(), e);
}

运行,ok了

转载请注明出处 https://www.cnblogs.com/majianming/p/9539376.html

在spring boot 中使用itext和itextrender生成pdf文件的更多相关文章

  1. wkhtmltopdf+itext实现html生成pdf文件的打印下载(适用于linux及windows)

    目中遇到个根据html转Java的功能,在java中我们itext可以快速的实现pdf打印下载的功能,在itext中我们一般有以下三中方式实现 配置pdf模板,通过Adobe Acrobat 来设置域 ...

  2. spring boot 中使用swagger 来自动生成接口文档

    1.依赖包 <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swa ...

  3. spring boot中利用mybatis-generator插件生成代码

    使用Idea在spring boot中集成mybatis-generator,自动生成mapper.xml  model  dao 文件 一.配置 pom.xml 在pom.xml的<plugi ...

  4. spring boot(三):Spring Boot中Redis的使用

    spring boot对常用的数据库支持外,对nosql 数据库也进行了封装自动化. redis介绍 Redis是目前业界使用最广泛的内存数据存储.相比memcached,Redis支持更丰富的数据结 ...

  5. Spring Boot中的事务管理

    原文  http://blog.didispace.com/springboottransactional/ 什么是事务? 我们在开发企业应用时,对于业务人员的一个操作实际是对数据读写的多步操作的结合 ...

  6. Spring Boot中的注解

    文章来源:http://www.tuicool.com/articles/bQnMra 在Spring Boot中几乎可以完全弃用xml配置文件,本文的主题是分析常用的注解. Spring最开始是为了 ...

  7. 在Spring Boot中使用Https

    本文介绍如何在Spring Boot中,使用Https提供服务,并将Http请求自动重定向到Https. Https证书 巧妇难为无米之炊,开始的开始,要先取得Https证书.你可以向证书机构申请证书 ...

  8. Spring Boot中使用Swagger2构建强大的RESTful API文档

    由于Spring Boot能够快速开发.便捷部署等特性,相信有很大一部分Spring Boot的用户会用来构建RESTful API.而我们构建RESTful API的目的通常都是由于多终端的原因,这 ...

  9. Dubbo在Spring和Spring Boot中的使用

    一.在Spring中使用Dubbo 1.Maven依赖 <dependency> <groupId>com.alibaba</groupId> <artifa ...

随机推荐

  1. 重载和重写在jvm运行中的区别(一)

    1.重载(overload)方法 对重载方法的调用主要看静态类型,静态类型是什么类型,就调用什么类型的参数方法. 2.重写(override)方法 对重写方法的调用主要看实际类型.实际类型如果实现了该 ...

  2. RGB中的颜色的设置

    用来表示一个 RGB 颜色值. 语法 RGB(red, green, blue) RGB 函数的语法含有以下这些命名参数: 部分 描述 red 必要参数:Variant (Integer).数值范围从 ...

  3. WebApi-路由机制 Visual Studio 2015中的常用调试技巧分享

    WebApi-路由机制   一.WebApi路由机制是什么? 路由机制通俗点来说:其实就是WebApi框架将用户在浏览器中输入的Url地址和路由表中的路由进行匹配,并根据最终匹配的路由去寻找并匹配相应 ...

  4. CRF图像切割简单介绍

    这里主要是讲Conditional Random Fields(CRF)用于pixel-wise的图像标记(事实上就是图像切割).CRF经经常使用于 pixel-wise的label 预測.当把像素的 ...

  5. 我的家乡:三河古镇已经登上央视CCTV-1新闻联播啦!

    在烟雨朦胧时走在古镇的青石街上,别有一番风味!第一幅图为央视的直播车,第二副图为漂亮的三河夜景色!

  6. 有关java构造器的笔记

    当程序中首次出现使用一个类A时, 无论是使用A的静态成员还是创建一个对象(声明一个A类对象不算), 那么类加载器就会首先对A进行加载, 在对A进行加载的过程中, 如果A有一个extends的父类B, ...

  7. jQuery的AJax异步訪问

    用一个样例用以说明:点击button,将input内用户输入的数据发送给服务端.并将结果返回给页面. 首先是html承载内容: <!DOCTYPE html> <html> & ...

  8. 2016/3/27 PHP中include和require的区别详解

    1.概要 require()语句的性能与include()相类似,都是包括并运行指定文件.不同之处在于:对include()语句来说,在执行文件时每次都要进行读取和评估:而对于require()来说, ...

  9. Java数据类型的分类

    java支持的类型分为两类:基本类型和引用类型 一.基本类型 4类8种: (1)整型:int.short.long.byte. (2)浮点型:float.double. (3)字符型:char. (4 ...

  10. XMU 1071 圣斗士黄金十二宫(七)银河星爆 【计算几何】

    1071: 圣斗士黄金十二宫(七)银河星爆 Time Limit: 500 MS  Memory Limit: 64 MBSubmit: 193  Solved: 10[Submit][Status] ...