一、背景
在一个项目中需要打印页面出pdf,需要有页眉与页脚,同时,最好容易部署。
二、问题出现
找了几个pdf库,包括unipdf,chromedp,以及强大的wkhtmltopdf还有啥的,忘了。
unipdf不支持打印url直接pass,wkhtmltopdf需要配置,也直接pass。本以为chromedp不需要特别配置,就开始用来开发了。谁知道后面因此花了1天时间研究依赖安装问题。
三、现象
我们程序本地跑完后,一切正常,部署到线上docker中,发现无法生成pdf,报错:google-chrome不在&PATH中。原来,因为自己电脑上安装了chrome,所以跑起来没问题。
分析一轮,原来docker中也是需要安装依赖的,然后就开始找怎么安装。
结论是如下
FROM alpine:latest
# 安装编译工具和依赖项
# 设置环境变量
ENV CHROMEDP_EXEC_PATH=/usr/bin/chromium-browser
# 安装Go、chromium浏览器及其依赖项
RUN apk add --no-cache \
bash \
ca-certificates \
chromium \
freetype \
freetype-dev \
harfbuzz \
libstdc++ \
ttf-freefont \
nss \
&& mkdir /app \
&& mkdir -p /root/go/src /root/go/bin /root/go/pkg
# 安装中文字体
RUN apk add --no-cache font-noto-cjk
最后的文字是因为直接使用打印出的pdf中文乱码问题。
四、页眉页脚设置
新版的库是允许编辑页眉的,怎么使用,如下:特别提醒,有图片需要转成base64格式。
func printToPDF(urlstr string, res *[]byte) chromedp.Tasks {
header_template := `
<html>
<head>
<style>
.watermark {
position: absolute;
top: 10px; /* 调整位置以符合你的需求 */
left: 10px; /* 调整位置以符合你的需求 */
z-index: 9999;
opacity: 0.5; /* 可选:调整水印的透明度 */
}
.watermark img {
height: 50px; /* 根据你的水印PNG调整大小 */
width: auto;
}
</style>
</head>
<body>
<div style="display:flex" class="watermark">
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhE" alt="Watermark">
</div>
<span class="title">你的练习</span>
</body>
</html>
`
footer_template := `<div style="position: absolute; bottom: 10px; right:0.2043in; font-size: 12px;display:flex">Page <div style="margin:0 5px" class="pageNumber">{{pageNumber}}</div> of <div style="margin:0 5px" class="totalPages">总页数: {{totalPages}}</div></div>`
return chromedp.Tasks{
chromedp.Navigate(urlstr),
chromedp.ActionFunc(func(ctx context.Context) error {
pageinfo := page.PrintToPDF()
pageinfo.DisplayHeaderFooter = true
pageinfo.FooterTemplate = footer_template
pageinfo.HeaderTemplate = header_template
pageinfo.MarginTop = 0.8
pageinfo.MarginBottom = 0.4
buf, _, err := pageinfo.WithPrintBackground(false).Do(ctx)
if err != nil {
return err
}
*res = buf
return nil
}),
}
}