目前html转换成pdf技术已经非常的成熟了,总的概括下来分那么两种,一是通过浏览器的Print功能,代码模拟浏览器的Print操作,或者调用浏览器内核Print功能把html的网页转换成PDF文件,这种方式要求html的代码符合W3C规范,比较严格,并且需要浏览器支持Print操作。其二是一些第三方库可以将HTML渲染转换为PDF,这些库转换出来的PDF文件还可以通过修改CSS样式进行对PDF文件编辑,比较灵活,下面我们对这两种情况使用golang进行演示。
我们都知道Chrome是支持print功能的,比如右键当前页面就会出来一个菜单如下:
那么这里点击“打印...”就会出现如下页面,就可以另存为PDF了。
那么其实呢,如果了解谷歌浏览器开发者工具的都知道,在console中使用一行命令就可以实现上述的流程,即:
window.print()
输入回车后弹窗跟上面类似。
所以我们可以利用开发者工具协议Chrome DevTools Protocol实现上述操作。
这里就需要引入一个go的库https://github.com/chromedp/chromedp.git,感兴趣的可以上去了解下。它是基于谷歌浏览器开发者工具协议实现了一套接口,方便操作。
1。首先安装这个库:
go get github.com/chromedp/cdproto
##################################
$ go get github.com/chromedp/cdproto
go: downloading github.com/chromedp/cdproto v0.0.0-20240102194822-c006b26f21c7
go: downloading github.com/mailru/easyjson v0.7.7
go: downloading github.com/chromedp/sysutil v1.0.0
go: downloading github.com/josharian/intern v1.0.0
go: added github.com/chromedp/cdproto v0.0.0-20240102194822-c006b26f21c7
go: added github.com/chromedp/sysutil v1.0.0
go: added github.com/josharian/intern v1.0.0
go: added github.com/mailru/easyjson v0.7.7
2。使用
demo代码如下:
package main
import (
"context"
"fmt"
"log"
"os"
"github.com/chromedp/cdproto/page"
"github.com/chromedp/chromedp"
)
func main() {
// create context
ctx, cancel := chromedp.NewContext(context.Background())
defer cancel()
// capture pdf
var buf []byte
if err := chromedp.Run(ctx, printToPDF(`https://www.google.com/search?q=chrome+%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8%E5%BC%80%E5%8F%91%E8%80%85%E5%B7%A5%E5%85%B7+print%E5%8A%9F%E8%83%BD&sca_esv=597229899&ei=Pr-eZZWUE5HR2roP776JyAw&ved=0ahUKEwiVq5LNmNODAxWRqFYBHW9fAskQ4dUDCBA&uact=5&oq=chrome+%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8%E5%BC%80%E5%8F%91%E8%80%85%E5%B7%A5%E5%85%B7+print%E5%8A%9F%E8%83%BD&gs_lp=Egxnd3Mtd2l6LXNlcnAiLmNocm9tZSDlpoLkvZXkvb_nlKjlvIDlj5HogIXlt6XlhbcgcHJpbnTlip_og70yCBAhGKABGMMEMggQIRigARjDBDIIECEYoAEYwwRIoCRQ4AdY3hNwAXgAkAEBmAHpAqAB_QqqAQcwLjcuMC4xuAEDyAEA-AEBwgIKEAAYRxjWBBiwA8ICCBAAGIAEGKIEwgIMECEYChigARjDBBgq4gMEGAAgQYgGAZAGAg&sclient=gws-wiz-serp#ip=1`, &buf)); err != nil {
log.Fatal(err)
}
if err := os.WriteFile("test.pdf", buf, 0o644); err != nil {
log.Fatal(err)
}
fmt.Println("wrote test.pdf")
}
// print a specific pdf page.
func printToPDF(urlstr string, res *[]byte) chromedp.Tasks {
return chromedp.Tasks{
chromedp.Navigate(urlstr),
chromedp.ActionFunc(func(ctx context.Context) error {
buf, _, err := page.PrintToPDF().WithPrintBackground(false).Do(ctx)
if err != nil {
return err
}
*res = buf
return nil
}),
}
}
[Running] go run "/Users/xxx/go-proj/Untitled-1.go"
wrote test.pdf
运行结果如上,我们可以检查下是否生成。
可以看到上图生成结果,唯一不一样的是这里生成了两页,不过最终也是生成了。各位看官感兴趣也可以去了解下其代码实现原理。
比较流行的有gofpdf,go-wkhtmltopdf和调用wkhtmltopdf的命令转换。这里演示下使用go-wkhtmltopdf
库。可以去https://github.com/SebastiaanKlippert/go-wkhtmltopdf这里看下.
1。先安装wkhtmltopdf 可以去https://wkhtmltopdf.org/downloads.html下载
$ wkhtmltopdf --version
wkhtmltopdf 0.12.6 (with patched qt)
2。安装github.com/SebastiaanKlippert/go-wkhtmltopdf
3。代码:
package main
import (
"fmt"
"log"
wkhtmltopdf "github.com/SebastiaanKlippert/go-wkhtmltopdf"
)
func main() {
// Create new PDF generator
pdfg, err := wkhtmltopdf.NewPDFGenerator()
if err != nil {
log.Fatal(err)
}
// Set global options
pdfg.Dpi.Set(300)
pdfg.Orientation.Set(wkhtmltopdf.OrientationLandscape)
pdfg.Grayscale.Set(true)
// Create a new input page from an URL
page := wkhtmltopdf.NewPage("https://www.baidu.com/")
// Set options for this page
page.FooterRight.Set("[page]")
page.FooterFontSize.Set(10)
page.Zoom.Set(0.95)
// Add to document
pdfg.AddPage(page)
// Create PDF document in internal buffer
err = pdfg.Create()
if err != nil {
log.Fatal(err)
}
// Write buffer contents to file on disk
err = pdfg.WriteFile("./test_go-wkhtmltopdf.pdf")
if err != nil {
log.Fatal(err)
}
fmt.Println("Done")
// Output: Done
}
4。执行和结果:
[Running] go run "/Users/xxx/go-proj/Untitled-1.go"
Done
缺点是执行的速度太慢了,它似乎需要把网页都下载下来才能完成渲染和打印。
gofpdf这个库也是相当强大,他能编辑已有的pdf,也可以自己生成pdf文件,有条件的同学可以细细研究,这里不再赘述。
本文介绍了使用golang如何将html转换成pdf的过程。演示了基于chrome的开发工具和基于wkhtmltopdf第三方库的简单使用方法,均将页面最终转换为pdf文件。综合比较也是各有千秋,根据自己的场景去选择合适的库才是王道。本人才疏学浅,如有不足请评论区斧正。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。