以前很菜的時候收過這個需求
真心很討厭PDF,因為要自己算座標和設定一堆東西
後來這個需求就被棄置了,也沒繼續研究
直到最近坑又被挖出來了
拜各位大神賜教,這禮拜試過很多方法,終於實作出來幾種方法,真的非常感謝
然後我要去刻畫面了==

PDF大評比
  • maroto:很好上手,但是option很少
  • gofpdf:難度稍高,幾乎什麼都可以設定,但有些還是沒辦法,還有一些issue,沒維護了,好處是不用依賴driver
  • html template + wkhtmltopdf:看到後來才想到之前很菜的時候就是這樣做的,我真是蠢= =,好處是html會幫你搞定一切,什麼都可以設定,缺點是要依賴一個driver
driver & package
網址留作紀念,因為有可能會搜尋到另一個封裝起來的同名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>
參考資料