以前很菜的時候收過這個需求
真心很討厭PDF,因為要自己算座標和設定一堆東西
後來這個需求就被棄置了,也沒繼續研究
直到最近坑又被挖出來了
拜各位大神賜教,這禮拜試過很多方法,終於實作出來幾種方法,真的非常感謝
然後我要去刻畫面了==
- maroto:很好上手,但是option很少
- gofpdf:難度稍高,幾乎什麼都可以設定,但有些還是沒辦法,還有一些issue,沒維護了,好處是不用依賴driver
- html template + wkhtmltopdf:看到後來才想到之前很菜的時候就是這樣做的,我真是蠢= =,好處是html會幫你搞定一切,什麼都可以設定,缺點是要依賴一個driver
網址留作紀念,因為有可能會搜尋到另一個封裝起來的同名package,要找資料也方便
html template + wkhtmltopdf如何使用
要灌driver
- wkhtmltopdf或brew都行
用go mod
package的坑
手動import "github.com/SebastiaanKlippert/go-wkhtmltopdf"
github上面的quick start是在他的test file裡寫的
你會不知道要用什麼開頭import
用go mod之後package引用只要加上wkhtmltopdf就不用在import前面加上alias
ex:wkhtmltopdf.NewPDFGenerator()
原理
1.利用html template將html檔參數化可以injection parameters
2.excute成byte檔給wkhtmltopdf去生成頁面
注意1:謹慎使用html template,因為可能有injection風險,千萬不要信任來路不明的html檔,詳細請參閱html template
注意2:要是頁面太多,package會自動AddPages,不用擔心
Go程式碼
func GeneratePDF() error {
Student := struct {
Title string
}{
"My Awesome Site 123",
}
htmlTemp, err := template.ParseFiles("./example.html")
if err != nil {
log.Fatal(err)
return err
}
var buf bytes.Buffer
htmlTemp.Execute(&buf, &Student)
pdfg, err := wkhtmltopdf.NewPDFGenerator()
if err != nil {
log.Fatal(err)
}
pdfg.AddPage(wkhtmltopdf.NewPageReader(bytes.NewReader(buf.Bytes())))
pdfg.Dpi.Set(600)
err = pdfg.Create()
if err != nil {
log.Fatal(err)
}
err = pdfg.WriteFile("./simplesample.pdf")
if err != nil {
log.Fatal(err)
}
return nil
}
html
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8"> <!-- 有中文要加這行,不然亂碼 -->
<title>{{ .Title }}</title>
</head>
<body>
<h1>{{ .Title }}</h1> <!-- 想測試自動分頁的把這行複製一堆就可以 -->
</body>
</html>
參考資料