首先,先说明一下需求,之所以需要生成PDF中文文档,是因为网站需要生成打印用户的报名表信息。因此将踩过的坑记录下来。

Python版本 3.7.4

reportlab包的版本 3.5.31

Linux版本 Centos7

在作出说明之前,首先大家可以参考reportlab的官方英文文档,文章后面已附带上了。

如果是有了一定的reportlab基础的,并且只想解决加载中文的问题的,可以直接跳到最后,看核心代码。希望看了后留个赞^ _ ^

一、reportlab的字体和编码问题:

根据官方手册的说明,Unicode和UTF8是默认的输入编码。
以下内容是根据手册翻译的相关说明:

3.1 Unicode和UTF8是默认的输入编码
从reportlab 2.0版(2006年5月)开始,您提供给我们的API的所有文本输入都应使用UTF8或Python Unicode对象。 这适用于canvas.drawString和相关API的参数,表单元格内容,图形对象参数和段落源文本。
我们考虑过使输入编码可配置,甚至取决于语言环境,但决定“显式比隐式更好”。
这简化了我们以前有关希腊字母,符号等的许多工作。 要显示字符,请找出其Unicode代码点,并确保所使用的字体能够显示它。
如果要改用ReportLab 1.x应用程序,或从另一个包含单字节数据的源中读取数据(例如latin-1或WinAnsi),则需要转换为Unicode。 Python编解码器软件包现在包括所有常见编码(包括亚洲编码)的转换器。

3.2替代字体的自动输出
代码中仍然有很多地方,包括rl_config默认的Encoding参数,以及传递给各种Font构造函数的参数,这些参数引用了编码。 在过去人们需要使用PDF查看设备支持的Symbol和ZapfDingbats字体中的字形时,这些功能很有用。 默认情况下,标准字体(Helvetica,Courier和Times Roman)将提供Latin-1中可用的字形。 但是,如果我们的引擎检测到不在字体中的字符,它将尝试切换到Symbol或Za pfDingbats来显示这些字符。 例如,如果在对drawString的调用中包括一对面向右的scis sors的Unicode字符\ u2702,则应该看到它们(有一个示例intest_pdfgen_general.py/pdf)。 无需在代码中切换字体。

3.3使用非标准的Type 1字体
如上一章所述,每个Acrobat Reader副本都内置了14种标准字体,因此ReportLab PDF库只需要按名称引用即可。 如果要使用其他字体,它们必须可用于您的代码,并将嵌入到PDF文档中。
您可以使用下面描述的机制在文档中包括任意字体。 我们有一个名为DarkGardenMK的开源字体,我们可以将其用于测试和/或记录目的(也可以使用)。 它与ReportLab分发包捆绑在directoryreportlab / fonts中。
现在,字体嵌入依赖于Adobe AFM(‘Adobe Font Metrics’)和PFB(‘Printer Font Binary’)格式的字体描述文件。 前者是一个ASCII文件,包含有关字体中字符(“字形”)的信息,例如高度,宽度,边界框信息和其他“度量”,而后者是描述字体形状的二进制文件。 reportlab / fonts目录包含用作示例字体的文件“ DarkGardenMK.afm”和“ DarkGardenMK.pfb”。
在DarkGardenMK示例中,我们明确指定了要加载的字体描述文件的位置。 一般而言,您宁愿将字体存储在某些规范的位置,并使嵌入机制知道它们。 使用在本节开始时已经看到的相同配置机制,我们可以指定Type-1字体的默认搜索路径。
不幸的是,对于这样的位置(甚至不在同一平台上),还没有可靠的标准,因此,您可能必须编辑reportlab / rl_config.py文件来修改T1SearchPathidentifier的值以包含其他目录。 我们自己的建议是在开发中使用reportlab / fontsfolder。 并在任何类型的受控服务器部署中将所需的字体作为应用程序的打包部分。 这样可以使您免受其他软件或系统管理员正在安装和卸载的字体的影响。

关于缺少字形的警告
如果指定编码,通常会假定字体设计者已提供了所有需要的字形,但是并不总是如此。 在我们的示例字体中,字母出现了,但是缺少许多符号和重音符号。 字体的默认行为是打印一个’notdef’字符-通常是斑点,点或空格-当传递该字符时它将无法绘制。 但是,您可以要求图书馆发出警告。 下面的代码(在加载字体之前执行)将导致在注册时针对未包含在字体中的任何字形生成警告。
import reportlab.rl_config
reportlab.rl_config.warnOnMissingFontGlyphs = 0

3.4标准单字节字体编码
本节向您显示常用编码中可用的字形。
下面的代码表显示了WinAnsiEncoding中的字符。 这是Windows和美国和西欧的许多Unix系统上的标准编码。 它也被称为代码页1252,实际上与ISO-Latin-1相同(它包含一个或两个额外的字符)。 这是Reportlab PDF库使用的默认编码。 它是由reportlab / lib,codecharts.py中的标准例程生成的,可用于显示字体的内容。 沿边缘的索引号以十六进制表示。

内容可能有点多,但是看看了解了就好,主要明白,它默认使用的是Unicode和UTF-8的编码格式即刻。噢,对了另外说一下,在python2中字符传unicode码是使用unicode函数,而python3中只需要使用str()函数就可以了。

二、导入reportlab的注册字体模块,并注册字体

import reportlab.pdfbase.ttfonts #导入reportlab的注册字体模块
tem = reportlab.pdfbas e.ttfonts.TTFont('song','simsun.ttc') #导入字体
reportlab.pdfbase.pdfmetrics.registerFont(tem) #注册当前目录下的字体

为了项目方便我直接将要使用的字体放在了当前目录下,在实际下项目中,需要改变TTFont的第二个参数给与实际的指定路径。而TTFont的第一个参数是指定这个字体的名字,在后面我们使用canvas的描绘工具时,就可以使用这个名字去指定对应的字体了。

三、下面使用了手册里面的一个例子,详细内容见注释

from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer,Table,TableStyle
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.lib import colors
from reportlab.rl_config import defaultPageSize  #导入默认页面大小,一个数组
from reportlab.lib.units import inch  #导入英寸的单位,一个inch代表一英寸
#上面导入的库都模块都会用到,主要解释一下第一个导入语句导入的东西
#SimpleDocTemplate是reportlab的一个简单文档模板,关于模板的使用手册里面也有。使用它可以快速方便的生成文档
#Paragraph是设置文章的段落格式,将指定的字符串内容形成能够被SimpleDocTemplate对象填充使用的内容
#Spacer是用来填充指定大小的空白内容的方法
#Table实用来生成一个SimpleDocTemplate对象中的表格内容,最后在文档中展示一个表格。
#TbleStyle功能如其名。简单的说一下,reportlab中的表格功能是很强大的,详细的使用见手册。PAGE_HEIGHT=defaultPageSize[1]  #从导入的默认页面大小中,获得对应的页面高度与页面宽度
PAGE_WIDTH=defaultPageSize[0]  #获取宽度
styles = getSampleStyleSheet()  #获取简单的样式表格
# 首先,我们从其他模块导入一些构造函数,一些段落样式以及其他便利。Title = "Hello Table"
pageinfo = "页"def myFirstPage(canvas, doc):  #设置首页,参数格式固定canvas.saveState()  #保存之前的画笔格式等状态,并设置新的状态canvas.setFont('song',5)   #使用注册的字体text = '页眉文本''canvas.drawString(PAGE_WIDTH/5.0,PAGE_HEIGHT-50, str(text))   #前两个参数是设置画笔所绘值的文字所在的位置,其起始坐标是页面的左下角,第一个参数是设置x的位置,第二个参数设置y的位置canvas.setFont('Times-Bold',16)  #设置新的样式canvas.drawCentredString(PAGE_WIDTH/2.0, PAGE_HEIGHT-108, Title)  #绘制居中文本到页面上canvas.setFont('song',9)canvas.drawString(inch, 0.75 * inch, "第 1 %s" % pageinfo)  # 设置第一页的页脚;可以看出,页脚是直接画在相应的位置的,也就是说,需要我们手动的调出页脚所在的合适位置。但是一般来说,都是左边句1*inch,下边剧0.75*inch。canvas.restoreState()  #将画笔格式等状态还原
# 我们使用上述功能定义文档首页的固定功能。def myLaterPages(canvas, doc):   #设置其他页canvas.saveState()  #保存之前画笔的格式canvas.setFont('song',9)  #设置新的样式canvas.drawString(inch, 0.75 * inch, "第 %d %s" % (doc.page, pageinfo))   #填充新的内容canvas.restoreState  #画笔样式还原
# 因为我们希望第一页之后的页面看起来与第一页不同,所以我们为其他页面的固定功能定义了一种替代布局。
#  请注意,以上两个函数使用pdfgen级画布操作来绘制页面的注释。def go():import reportlab.pdfbase.ttfonts #导入reportlab的注册字体reportlab.pdfbase.pdfmetrics.registerFont(reportlab.pdfbase.ttfonts.TTFont('song', 'simsun.ttc')) #注册当前目录下的字体,宋体doc = SimpleDocTemplate("phello.pdf")  #生成一个模板的对象doc,给出指定的文件类型对象或者文件名,没有的该文件则会新生成Story = [Spacer(1,0.5*inch)]  #使用Story列表来存储添入文档中的内容,先填入开头的部分空白区域style = styles["Normal"]  #选着默认中的正常格式 style.fontName = 'song'  #使用自己注册的字体data = [              #生成一个表格中的数据,必须是一个是一个二维数组[1,2,3,4,5],[5,4,3,2,1],[2,3,4,5,1],[3,4,5,1,2],]t = Table(data,5*[1*inch],4*[0.8*inch]) #使用表格数据生成一个表格对象,可以被用来填入文档模板对象doct.setStyle(TableStyle([  #使用表格的setStyle方法设置表格样式,其样式是一个Tabletyle对象,对应的样式设置内容请查阅手册('BACKGROUND',(1,1),(-2,-2),colors.green),('TEXTCOLOR',(0,0),(1,-1),colors.red),('BOX',(0,0),(-1,-1),2,colors.black),  #BOX命令设置边框('BOX',(0,0),(1,-1),1,colors.red),('BOX',(0,0),(-1,0),3,colors.blue),('LINEABOVE',(0,1),(-3,1),5,colors.blue),]))Story.append(t)    #将表格添加到模板对象for i in range(100):   #遍历添加正文信息,添加每一个段落。bogustext = ("This is Paragraph number %s. " % i) *20 #将文本复制20遍,再输出到填充对相中p = Paragraph(bogustext, style)  #使用Paragraph对内容设置段落格式style,必须要对这种内容设置段落格式才可以保存到doc对象中Story.append(p)   #添加段落内容到列表,内容必须要经过Paragraph方法加上格式处理后才能正常的绘制Story.append(Spacer(1,0.2*inch))   #在上面的信息填充完毕之后,再添入空格区域,形成段落间距的效果;doc.build(Story, onFirstPage=myFirstPage, onLaterPages=myLaterPages) #使用doc的build方法建立文档,其中三个参数的含义一目了然。# onFirstPage设置第一页的样式,onLaterPages设置其他页的样式,具体的样式通过对应的函数定义# 最后,我们创建一个Story并构建文档。 # 请注意,我们在此使用的是“罐头”文档模板,该模板随页面模板一起预先构建。 # 我们还使用了预先构建的段落样式。 # 我们在这里仅使用两种类型的可流动物-Spacers(空白间隔)和Paragraphs(段落)。 # 第一个空格键确保Paragraphs跳过标题字符串。go()  #执行主逻辑函数

四、运行结果的效果

五、总结:

如果需要使用中文字体在reportlab中表现出来,我们需要使用先加载相应目录下的字体,然后再注册该字体为对应的字体名称,后面即可以在各种样式设置中使用它。
以下是核心代码。

import reportlab.pdfbase.ttfonts #导入reportlab的注册字体reportlab.pdfbase.pdfmetrics.registerFont(reportlab.pdfbase.ttfonts.TTFont('song', 'simsun.ttc')) #注册当前目录下的字体,宋体

在Centos7下使用reportlab输出中文到pdf文档相关推荐

  1. php操作pdf文档输出,PHP生成PDF文档实用技巧

    PHP生成PDF文档实用技巧 实际工作中,我们要使用PHP动态的创建PDF文档,目前有许多开源的PHP创建PDF的类库,今天我给大家来介绍一款优秀的PDF库,它就是TCPDF,TCPDF是一个用于快速 ...

  2. iText创建一个含有中文的pdf文档

    有朋友问我pdfbox支不支持向pdf文档中写入中文.然后试了好多遍都是有乱码,也找了好多资料没有找到解决办法. 但是在查找资料的过程中发现了另一个处理pdf的开源库iText.官方介绍 http:/ ...

  3. (转载)中文Appium API 文档

    该文档是Testerhome官方翻译的源地址:https://github.com/appium/appium/tree/master/docs/cn官方网站上的:http://appium.io/s ...

  4. 使用texlive输出包含数学公式的文档

    一. texlive语法排版很复杂,但安装却很简单,这是商品社会的胜利.texlive语法可以写数学公式,画数学图像,填补了office软件在科学文档上功能略弱的不足.硕士生.博士生比较聪明,通过阅读 ...

  5. 中文 Appium API 文档

    该文档是Testerhome官方翻译的 源地址:https://github.com/appium/appium/tree/master/docs/cn 官方网站上的:http://appium.io ...

  6. 通过FPDF创建中文PDF文档

    FPDF是个免费的PHP库可以用来创建PDF文档,但是官网提供的原始类库文件不支持中文. 还好有先驱者已经解决了这个问题,需要下载中文库支持文件:http://www.fpdf.org/downloa ...

  7. 使用poi写入doc文档中文档打不开_基于NodeJS和浏览器的PDF文档引擎——PDFKit

    介绍 PDFKit是一个用于Node和浏览器的PDF文档生成库,可以轻松创建复杂的多页面可打印文档.API包含可链接性,包括低级功能以及更高级功能的抽象.PDFKit API设计简单,因此生成复杂文档 ...

  8. 如何将英文pdf文档在线翻译成中文?

    我们都要掌握一些办公技巧,像pdf翻译就是必不可少的,如何将英文pdf文档在线翻译成中文的,这个对英语差的来说简直就是福利,接着我就来发放一波福利. 1.打开浏览器输入迅捷在线PDF转换器,并在搜索结 ...

  9. itext生成pdf文档加载中文字体解决方法

    最近接手一个任务,在网页中通过用户的输入的信息生成一个pdf文档并且下载到用户本地.iText是用于生成PDF文档的一个java类库.通过iText不仅可以生成PDF或rtf的文档,而且可以将XML. ...

最新文章

  1. 微信小程序request合法域名怎么配置啊
  2. 如何在 Windows 7 中使用多线程加快文件复制[转]
  3. 数据库系统概论:第十一章 并发控制
  4. Py库下载:Dos内一条命令快速全部下载(先列出要下载的库名称保存为txt文件)
  5. 处理字符串_5_字符串里过滤不需要的字符
  6. Java 多线程Thread
  7. aws cognito_使用AWS Cognito的用户管理—(1/3)初始设置
  8. ai怎么生成条形码_中琅条码生成软件如何制作SCC-14条码
  9. 百度贴吧 2017 前贴子无法访问;网易腾讯游戏获批;苹果反垄断案败诉 | 极客头条...
  10. POJ-2488 A Knights Journey-深度优先搜索DFS
  11. Illustrator 教程,如何在 Illustrator 中重新着色图稿?
  12. 【CVPR2005】梯度方向直方图(Histogram of Oriented Gradients,简称HOG)
  13. 科研绘图必备软件简介
  14. 小米路由器4A千兆版c341编程器刷breed.bin详细教程
  15. 王垠面阿里P9,面跪后与P10赵海平互怼:人性最大的愚蠢,是互相为难
  16. 发送邮件,javax.mail 与 geronimo-javamail_1.4_spec 的jar包冲突
  17. python断点续传下载_Python 3 爬虫|第12章:并发下载大文件 支持断点续传
  18. 存储技术(一)-基本概念和技术发展
  19. 程序员辛酸泪——当程序员老去,程序员又何去何从
  20. 谁能顶得住,mybatis这十八连环问

热门文章

  1. Qemu中添加自定义命令
  2. 推荐一款清理系统还算干净的软件MacBooster 7 for mac
  3. prop-Types验证
  4. c语言 通过openssl进行rsa的加密和解密
  5. 用python画玫瑰花的代码
  6. C++性能之战(4)--LeetCode 841 钥匙和房间(cin和cout加速)
  7. JavaScript 闭包(Closure)
  8. Linux初学者的学习指导
  9. 前端练习-----360手机桌面(记录篇)
  10. 应用层 HTTP 请求行