在写系统时,总是会遇见需要给用户提供pdf下载的功能,pdf生成方式多种多样,有通过前端生成pdf,也有使用后端生成pdf的方式。在这篇文章前已经有写过生成pdf的文章,使用的是php调用wkhtmltopdf的方式,部署在windows上,写这篇文章的时候,使用django作为后端,部署在ubuntu上,并且生成的pdf中有echarts绘制的图,所以写了这篇新的文章,有兴趣的可以去看看之前的文章最完美的html转化为pdf的方法
wkhtmltopdf安装wkhtmltopdf是一个使用 Qt WebKit 引擎做渲染的,能够把html 文档转换成 pdf 文档 或 图片(image) 的命令行工具,支持多个平台,可在win,linux,os x 等系统下运行。
多平台的优势让你可以无痛切换系统使用
可以前往官网下载符合条件的安装包wkhtmltopdf下载官网
我的服务器系统是ubuntu20.04,直接使用命令wget https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6-1/wkhtmltox_0.12.6-1.focal_amd64.deb下载安装包。(有时候命令行很酷,但是会被网速一棒子打死,请选择你能下载下来的方式)
下载完进行安装sudo dpkg -i wkhtmltox_0.12.6-1.focal_amd64.deb
输入wkhtmltopdf -V显示版本号即安装成功
这是一个命令行工具,可以简单地拿百度主页尝试一下,输入命令行wkhtmltopdf http://baidu.com test.pdf
发现当前目录下出现一个test.pdf,效果如下。
python调用wkhtmlpdf现在只需要用python代码来执行该软件就能生成pdf,将pdf提供给用户下载,python控制wkhtmltopdf十分方便,只需要pip安装一个包,命令行执行pip install pdfkit
先简单的写一个html界面
Title
控制器views.py代码
from django.shortcuts import render
def test(request):
return render(request, 'index/test.html')
路由规则urls.py代码
path('test', views.test),
显示界面
这个时候为点击按钮赋予一个点击事件,向后台请求pdf下载
Title
上面需要引入jquery文件,也可以直接改成a标签
Title
点击我下载
效果都是一样的,然后需要在views.py里在写一个控制器,来处理前端的请求
import pdfkit
from django.http import FileResponse
def pdf_download(request):
root_path = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
pdf_path = os.path.join(root_path, 'test.pdf')# pdf路径可以自己修改
options = {
'encoding': "utf-8",
# 'javascript-delay': '1000', # 添加页面延时js执行时间段 echarts
}
url = 'http://baidu.com' # 简单使用百度来实验,可以换成自己需要下载的页面,自己的文档什么的
pdfkit.from_url(url, pdf_path, options=options)
file = open(pdf_path, 'rb')
response = FileResponse(file)
response['Content-Type'] = 'application/octet-stream'
download_file_name = '嘎嘎嘎.pdf' # 如果取中文名,需要urlquote()编码转换
response['Content-Disposition'] = 'attachment;filename="' + urlquote(download_file_name) + '"'
return response
上面代码需要注意,如果是自己制作的有echarts的界面,需要加上参数’javascript-delay’,不然图会在还没绘制就被生成pdf,最后点击下载查看效果
上面使用的都是最简单的示例,有其他需求可以自己加入,像生成的pdf会保存在本地,那么需要设置好命名规范,可以使用时间戳来命名,当然时间久了生成的pdf文件会很多,这需要代码定时清理文件。示例中pdf下载是直接返回一个一个fileresponse对象,浏览会直接下载pdf。但如果是异步请求下载,那么返回一个fileresponse对象是无法让浏览器下载的,需要更多的处理。
排版上述示例都是简单的界面,在实际中需要生成的pdf往往会是页数很多的页面,像这种页数很多的网页需要排版,分页的地方如果会截断内容则需要做特别处理,我们可以使用一些css属性调整这种截断,处理使用最基础的高度设置外,可以利用打印属性来调整分页。最简单的在某一块div加上css属性,那么在生成pdf时候后面的内容会出现在下一页。其他属性都可以去尝试使用
| 属性 | 简介 |
|---|---|
| page | 检索或指定显示对象容器时使用的页面类型 |
| Page-break-before | 检索或设置对象之前出现的页分割符 |
| Page-break-after | 检索或设置对象之后出现的页分割符 |
| Page-break-inside | 检索或设置对象容器内部出现的页分割符 |
使用wkhtmltopdf生成pdf已经是我优先使用的pdf生成方式,无论是换框架还是换系统,wkhtmltopdf都能适用,该软件使用起来便捷,而且命令行执行,所有的语言都可以轻松的调用该软件,功能上不仅能生成pdf还能生成图片,效果好,功能强大。



