Edited at

GoでHTMLをPDFに出力する

More than 1 year has passed since last update.


はじめに :airplane_departure:

GoでHTMLからPDF出力する方法をまとめました。


環境構築 :park:


wkhtmltopdfのインストール

wkhtmltopdfというCLIツールをGoから呼ぶことになるので、

まずはこちらをインストールします。

公式Downloadsから、自分の環境にあったものを選択しましょう。

wkhtmltopdf.png

※macの場合は、brew caskでインストール可能が可能です。

brew cask install wkhtmltopdf


Goのライブラリをインストール

今回は、go-wkhtmltopdfを使用します

go get -u github.com/SebastiaanKlippert/go-wkhtmltopdf


ざっくりレシピ :meat_on_bone:


:one: URLから


main.go

package main

import (
"fmt"
"log"
"github.com/SebastiaanKlippert/go-wkhtmltopdf"
)

func main() {
// Create new PDF generator
pdfg, err := wkhtmltopdf.NewPDFGenerator()
if err != nil {
log.Fatal(err)
}
url := "https://google.com/"

pdfg.AddPage(wkhtmltopdf.NewPage(url))

// PDF作成
err = pdfg.Create()
if err != nil {
log.Fatal(err)
}

// 出力
err = pdfg.WriteFile("./google.pdf")
if err != nil {
log.Fatal(err)
}

fmt.Println("tada!")
}



結果

68747470733a2f2f71696974612d696d6167652d73746f72652e73332e616d617a6f6e6177732e636f6d2f302f39393837342f31633930373665372d313165322d646464312d646266312d3739306666336538623038652e6a706567.jpg


:two: ファイルから


main.go

package main

import (
"fmt"
"log"
"github.com/SebastiaanKlippert/go-wkhtmltopdf"
)

func main() {
// Create new PDF generator
pdfg, err := wkhtmltopdf.NewPDFGenerator()
if err != nil {
log.Fatal(err)
}
p := "./test.html"

pdfg.AddPage(wkhtmltopdf.NewPage(p))

// PDF作成
err = pdfg.Create()
if err != nil {
log.Fatal(err)
}

// 出力
err = pdfg.WriteFile("./test.pdf")
if err != nil {
log.Fatal(err)
}

fmt.Println("tada!")
}



:three: HTML文字列から


main.go

package main

import (
"fmt"
"log"
"github.com/SebastiaanKlippert/go-wkhtmltopdf"
"strings"
)

func main() {
// Create new PDF generator
pdfg, err := wkhtmltopdf.NewPDFGenerator()
if err != nil {
log.Fatal(err)
}
html := `
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<h1>こんにちは!!!</h1>
</body>
</html>`

pdfg.AddPage(wkhtmltopdf.NewPageReader(strings.NewReader(html)))

// PDF作成
err = pdfg.Create()
if err != nil {
log.Fatal(err)
}

// 出力
err = pdfg.WriteFile("./test.pdf")
if err != nil {
log.Fatal(err)
}

fmt.Println("tada!")
}



結果

test.jpg


:four: 複数のHTML文字列の場合

こちら、複数のHTMLを渡して、ページをうまいこと分けてくれないかなと思ったのですが、

もとのCLIツールの実装的に難しいそうです(標準入力は一つしか受け取れないので、、、)

Unable_to_generate_more_than_one_page_while_reading_different_htmls_·_Issue__7_·_SebastiaanKlippert_go-wkhtmltopdf.png

参考:

https://github.com/SebastiaanKlippert/go-wkhtmltopdf/issues/7#issuecomment-293183363

なので、代替案として ファイルに一度出力してから、そのパスを指定するが良さそうです。


main.go

package main

import (
"fmt"
"log"
"github.com/SebastiaanKlippert/go-wkhtmltopdf"
)

func main() {
// Create new PDF generator
pdfg, err := wkhtmltopdf.NewPDFGenerator()
if err != nil {
log.Fatal(err)
}
tmp1 := "./tmp/tmp1.html"
tmp2 := "./tmp/tmp2.html"
tmp3 := "./tmp/tmp3.html"

pdfg.AddPage(wkhtmltopdf.NewPage(tmp1))
pdfg.AddPage(wkhtmltopdf.NewPage(tmp2))
pdfg.AddPage(wkhtmltopdf.NewPage(tmp3))

// PDF作成
err = pdfg.Create()
if err != nil {
log.Fatal(err)
}

// 出力
err = pdfg.WriteFile("./test.pdf")
if err != nil {
log.Fatal(err)
}

fmt.Println("tada!")
}


このようにすると、3ページに分けてpdfを出力してくれます :tada:


おわりに :airplane_arriving:

PDF出力ってレガシーだなと思いつつも、BtoBとかだと避けられなかったりしますよね。

そんな時、こちらの記事がお役に立てば幸いです。