django+wkhtmltopdf后端生成pdf
在写系统时,总是会遇见需要给用户提供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提供给用户下载,后台框架使用的是django,python控制wkhtmltopdf十分方便,只需要安装一个包,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界面请求pdf下载
Title
需要引入js文件奥,如果麻烦,可以直接改成a标签
Title
点击我下载
效果都是一样的,然后需要在views.py里在写一个控制器,来提供pdf下载
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\': \'1000\',不然图会还没绘制就被下载,点击下载效果
上面使用的都是最简单的示例,有其他需求可以自己加入,像生成的pdf会保存在本地,那么需要命令规范,可以使用时间戳来命名,当然随着时间久了pdf文件会很多,这需要代码来维持pdf的数量,定时清理。示例中pdf下载是直接返回一个一个fileresponse对象。如果是异步请求下载,那么返回需要另做处理。
排版
上述写的都是简单的界面,在实际中需要生成的pdf往往是页数很多,像这种页数很多的网页需要排版,分页的地方要是会被截断则需要做特别处理,我们可以使用css属性调整,处理最基础的设置高度外,可以利用打印属性来调整。使用一下就可以知道效果,最简单的在某一块div加上css属性style=\"page-break-after:always\"
,那么在生成pdf时候后面的内容会出现在下一页。
属性 | 简介 |
---|---|
page | 检索或指定显示对象容器时使用的页面类型 |
Page-break-before | 检索或设置对象之前出现的页分割符 |
Page-break-after | 检索或设置对象之后出现的页分割符 |
Page-break-inside | 检索或设置对象容器内部出现的页分割符 |
心得
使用wkhtmltopdf次数已经是比较多了,无论是换了框架还是换了系统,都可以轻松的转换,使用起来十分方便,各种语言的调用十分完善,除了pdf还可以生成图片。功能真的强大。