LoginSignup
10
13

More than 5 years have passed since last update.

GoでHTMLをPDFに出力する

Last updated at Posted at 2017-11-21

はじめに :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とかだと避けられなかったりしますよね。
そんな時、こちらの記事がお役に立てば幸いです。

10
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
13