中文字体篇
首先不管你是纯代码写还是基于HTML转PDF,中文问题一直是一个问题。实际上不用像很多网站上以前给出的要修改源码咯或者引入一些汉字支持的jar包咯巴拉巴拉的。很简单,你下载一个字体,或者使用系统内置的中文字体也可以,只需要new一个中文字体即可:
BaseFont baseCnFont = BaseFont.createFont("/yourFontDir/yourFont.ttf",BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
Font cnFont = new Font(baseCnFont,fontSize,fontStyle,color);
如果想直接使用系统字体,路径直接指向系统自带的路径文件夹。
若出现*`Font '/yourFontDir/yourFont.ttf' with 'Identity-H' is not recognized`*这样的异常,请尝试在你的字体文件路径后面加上“**`,1`**”,即:
BaseFont.createFont("/yourFontDir/yourFont.ttf,1",BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
HTML转PDF篇
以前都是直接纯代码生成PDF,后来因为老板各种不定时改需求该样式,于是就开始转为使用HTML转PDF。随着itext的更新迭代,HTML转PDF一样的也变得简单了,你只需要额外引入一个xmlworker的jar包,如果你使用的是maven,那么你只需要添加:
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>x.x.x</version>
</dependency>
<dependency>
<groupId>com.itextpdf.tool</groupId>
<artifactId>xmlworker</artifactId>
<version>x.x.x</version>
</dependency>
然后直接上干货吧:
//定义一系列你网站上需要用到的字体文件,如果不需要的话定义一个中文字体文件即可
BaseFont baseCnFont = BaseFont.createFont("/yourFontDir/baseCnFont.ttf",BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
BaseFont cnF1 = BaseFont.createFont("/yourFontDir/font1.otf",BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
BaseFont cnF2 = BaseFont.createFont("/yourFontDir/font2.otc",BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
BaseFont cnF3 = BaseFont.createFont("/yourFontDir/font3.ttf",BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
Document doc = new Document(PageSize.A4);
//如果是web做下载,后面的传入response的输出流,同时需要设置response的ContentType以及指定Content-Disposition为attachment同时设定fileName,fileName记得URLEncoder
PdfWriter writer = PdfWriter.getInstance(doc,new FileOutputStream("/yourPDFoutputDir/demo.pdf"));
//设置页面边距
doc.setMargins(20, 20, 20, 20);
doc.open();
//这里可以代码创建pdf的部分页面(如更加精细的封面等)
//......
//设置HTML转PDF时页面边距(建议放在open方法前面,如果不放在open方法前面则必须后面加上newPage才能生效)
// doc.setMargins(20, 20, 20, 20);
// doc.newPage();
XMLWorkerHelper.getInstance().parseXHtml(writer, doc, new ByteArrayInputStream("HTML字符串,我个人是使用的第三方模板工具(如Beetl)直接读取HTML模板,然后填充数据生成HTML字符串".getBytes("UTF-8")),Charset.forName("UTF-8"),new FontProvider() {
@Override
public boolean isRegistered(String arg0) {
return false;
}
@Override
public Font getFont(String fontFamily, String charset, boolean arg2, float size, int style, BaseColor color) {
//根据CSS中不同的字体名返回不同的字体实例
if("cssFontName1".equalsIgnoreCase(fontFamily)){
return new Font(cnF1,size,style,color);
}else if("cssFontName2".equalsIgnoreCase(fontFamily)){
return new Font(cnF2,size,style,color);
}else if("cssFontName3".equalsIgnoreCase(fontFamily)){
return new Font(cnF3,size,style,color);
}else{
//默认字体
return new Font(baseCnFont,size,style,color);
}
}
});
doc.close();
需要注意的是itext对需要转成PDF的HTML要求非常严格,标签必须闭合,而且支持的CSS不多,有效效果可能需要有一定的HTML布局和CSS技巧才能实现。
如果仔细度过那个超入门的朋友会知道设置表头有一个固定表头的功能,比如表格很长的时候PDF自动分页了,原生代码可以做到每一页都显示表头。实际上看了下iText的源码发现HTML转PDF的时候也是可以的,iText支持一个CSS属性,只需要给你需要重复表头表尾的table标签设置css属性“repeat-header:yes
”或“repeat-footer:yes
”即可,然后将你需要重复的表头放在thead标签内,表尾放在tfoot标签内。例:
<table style="repeat-header:yes;repeat-footer:yes;">
<thead>
<tr>
<th>如果表格过长自动分页了,我是重复的表头1</th>
</tr>
<tr>
<th>如果表格过长自动分页了,我是重复的表头2</th>
</tr>
</thead>
<tbody>
<tr>
<td>内容....</td>
</tr>
<!-- ..... -->
<tr>
<td>内容....</td>
</tr>
</tbody>
<tfoot>
<tr>
<th>如果表格过长自动分页了,我是重复的表尾1</th>
</tr>
<tr>
<th>如果表格过长自动分页了,我是重复的表尾2</th>
</tr>
</tfoot>
</table>
使用代码写pdf的时候,如果某个小章节完毕了,我们需要另起一页直接new Page()
即可。在HTML生成pdf的时候也是有特殊的css属性来控制的,分别是page-break-after:always
和page-break-before:always
(还有一个page-break-inside属性,但测试没发现有什么特殊的效果)
<span style="page-break-after:always;">这段文字后面会重新分页</span>
<p>正常的文字流,但是因为前面元素强制在后面分页了,后面的文字也强制在前面分页了,因此这段文字会是顶头文字,也是这一页的唯一的文字。</p>
<span style="page-break-before:always;">这段文字前面会重新分页</span>
消除表格边框默认的间距则设置table的css添加:“border-collapse:collapse
”,然后再分别给table和td、th设置border,如果嫌边框太粗,可将边框宽度设置为小数
,如0.3px
本文地址:http://darren.ink/archives/67
总结:
<table repeat-header:yes; ">
<thead>
<tr>
</tr>
</thead>
</table>
就可以重复表头了
更多推荐
利用itext通过html生成pdf自动添加表头
发布评论