go-wkhtmltopdf

repository·master·Indexed 22 days ago

https://github.com/sebastiaanklippert/go-wkhtmltopdf

A pure Golang wrapper around the wkhtmltopdf command-line utility for generating PDF documents from HTML/CSS templates. It supports generating PDFs from URLs or io.Reader inputs, configuring global and page-specific options, and serializing PDFGenerator configurations to and from JSON.

Tokens
4.3K
Snippets
18
Records
20
Agent score
78%

What's inside go-wkhtmltopdf

  1. Configure the wkhtmltopdf executable path

    master

    The package automatically attempts to find the wkhtmltopdf executable by checking:

    1. The current directory
    2. The PATH and PATHEXT environment directories
    3. The WKHTMLTOPDF_PATH environment variable

    If you need to specify a custom path or change it during execution, use the SetPath() method.

    Warning: Since Go 1.19, running executables from the current directory is restricted by the os/exec package.

  2. Install go-wkhtmltopdf

    master

    Install the package using go get or your preferred Go dependency manager.

    Note: This package is a wrapper around the wkhtmltopdf command-line utility. You must have wkhtmltopdf installed on your system for this package to function.

    go get -u github.com/SebastiaanKlippert/go-wkhtmltopdf
  3. Serialize and reconstruct PDF Generator via JSON

    master

    You can prepare a PDF configuration on a client (where wkhtmltopdf might not be installed) and reconstruct it on a server (e.g., AWS Lambda) using JSON serialization.

    1. On the Client: Use NewPDFPreparer() to build the configuration. Use ToJSON() to export the object. Pages added via NewPageReader are automatically encoded as Base64 strings in the JSON.
    2. On the Server: Use NewPDFGeneratorFromJSON(io.Reader) to reconstruct the generator from the JSON data, then call Create() to generate the PDF.
    // Client code
    pdfg := NewPDFPreparer()
    htmlfile, _ := ioutil.ReadFile("testdata/htmlsimple.html")
    pdfg.AddPage(NewPageReader(bytes.NewReader(htmlfile)))
    pdfg.Dpi.Set(600)
    
    // Export to JSON
    jb, err := pdfg.ToJSON()
    
    // Server code
    // Reconstruct from JSON bytes
    pdfgFromJSON, err := NewPDFGeneratorFromJSON(bytes.NewReader(jb))
    err = pdfgFromJSON.Create()
    // Client code
    pdfg := NewPDFPreparer()
    htmlfile, err := ioutil.ReadFile("testdata/htmlsimple.html")
    if err != nil {
      log.Fatal(err)
    }
        
    pdfg.AddPage(NewPageReader(bytes.NewReader(htmlfile)))
    pdfg.Dpi.Set(600)
        
    // The contents of htmlsimple.html are saved as base64 string in the JSON file
    jb, err := pdfg.ToJSON()
    if err != nil {
      log.Fatal(err)
    }
        
    // Server code
    pdfgFromJSON, err := NewPDFGeneratorFromJSON(bytes.NewReader(jb))
    if err != nil {
      log.Fatal(err)
    } 
        
    err = pdfgFromJSON.Create()
    if err != nil {
      log.Fatal(err)
    } 
  4. How PageProvider works

    master

    The PageProvider interface is the abstraction used to define inputs for the PDF generator. Both Page (for files/URLs) and PageReader (for io.Reader inputs) implement this interface.

    Any type implementing PageProvider must provide:

    • Args() []string: The command-line arguments specific to that page (e.g., margins, headers).
    • InputFile() string: The filename or identifier (returns "-" for readers).
    • Reader() io.Reader: The actual data stream (returns nil for files/URLs).
  5. Initialize a PDFGenerator

    master

    To generate PDFs, use NewPDFGenerator(). This function initializes a new generator and automatically attempts to locate the wkhtmltopdf executable on your system by checking the current directory, your PATH, and the WKHTMLTOPDF_PATH environment variable.

    If you need to prepare a configuration without immediately searching for the binary (for example, to export settings to JSON), use NewPDFPreparer(). However, if you use NewPDFPreparer(), you must manually call SetPath(path) before calling Create().

    import "github.com/SebastiaanKlippert/go-wkhtmltopdf"
    
    generator, err := wkhtmltopdf.NewPDFGenerator()
    if err != nil {
    	// Handle error (e.g., wkhtmltopdf binary not found)
    }
  6. Generate a PDF from a URL

    master

    To generate a PDF from one or more URLs, create a PDFGenerator using NewPDFGenerator(), configure global and page-specific options, and add pages using NewPage(url). Finally, call Create() to generate the PDF in an internal buffer and WriteFile(path) to save it to disk.

    package main
    
    import (
      "fmt"
      "log"
      "github.com/SebastiaanKlippert/go-wkhtmltopdf"
    )
    
    func main() {
      // Create new PDF generator
      pdfg, err := NewPDFGenerator()
      if err != nil {
        log.Fatal(err)
      }
    
      // Set global options
      pdfg.Dpi.Set(300)
      pdfg.Orientation.Set(OrientationLandscape)
      pdfg.Grayscale.Set(true)
    
      // Create a new input page from an URL
      page := NewPage("https://godoc.org/github.com/SebastiaanKlippert/go-wkhtmltopdf")
    
      // 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("./simplesample.pdf")
      if err != nil {
        log.Fatal(err)
      }
    
      fmt.Println("Done")
    }
    package main
    
    import (
      "fmt"
      "log"
      "github.com/SebastiaanKlippert/go-wkhtmltopdf"
    )
    
    func main() {
    
      // Create new PDF generator
      pdfg, err := NewPDFGenerator()
      if err != nil {
        log.Fatal(err)
      }
    
      // Set global options
      pdfg.Dpi.Set(300)
      pdfg.Orientation.Set(OrientationLandscape)
      pdfg.Grayscale.Set(true)
    
      // Create a new input page from an URL
      page := NewPage("https://godoc.org/github.com/SebastiaanKlippert/go-wkhtmltopdf")
    
      // 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("./simplesample.pdf")
      if err != nil {
        log.Fatal(err)
      }
    
      fmt.Println("Done")
    }
  7. Generate a PDF from an HTML string or io.Reader

    master

    To use HTML content from memory (like a string or a bytes.Buffer) instead of a URL, use NewPageReader(io.Reader). This uses the stdin capability of wkhtmltopdf. You can combine any number of external HTML documents (HTTP(S) links) with at most one HTML document from stdin.

    html := "<html>Hi</html>"
    pdfgen.AddPage(NewPageReader(strings.NewReader(html)))
  8. Configure Global Options

    master

    Global options control the general behavior of the wkhtmltopdf process, such as output quality, margins, and orientation. Use the newGlobalOptions() function to initialize a globalOptions struct, then use the provided setter methods to configure specific settings. Once configured, call .Args() to retrieve the slice of command-line arguments ready for use in a command execution.

    // Example of configuring global options
    global := newGlobalOptions()
    global.Grayscale.Set(true)
    global.Orientation.Set(OrientationLandscape)
    global.PageSize.Set(PageSizeA4)
    
    args := global.Args()
  9. Add input pages to a PDF document

    master

    A PDFGenerator can consist of multiple input pages. You can add pages using AddPage(p PageProvider). There are two main ways to provide input:

    1. NewPage(input string): Used for local file paths or URLs. The input string is the source.
    2. NewPageReader(input io.Reader): Used for HTML content provided from memory (e.g., a buffer or a string converted to a reader). Only one PageReader can be used per document because it utilizes the command's stdin.

    Use SetPages([]PageProvider) to replace all existing pages or ResetPages() to clear them while keeping your configuration intact.

    // Example: Adding a URL page and a memory-based page
    
    // 1. From a URL
    p1 := wkhtmltopdf.NewPage("https://example.com")
    generator.AddPage(p1)
    
    // 2. From an io.Reader (memory)
    htmlContent := strings.NewReader("<html><body><h1>Hello</h1></body></html>")
    p2 := wkhtmltopdf.NewPageReader(htmlContent)
    generator.AddPage(p2)
  10. Serialize a PDFGenerator to JSON with ToJSON()

    master

    The ToJSON() method on a *PDFGenerator creates a complete JSON representation of the generator's configuration, including global options, outline options, cover, TOC, and all pages.

    If the generator contains pages using a PageReader, the content of those pages is automatically encoded as a Base64 string within the JSON to ensure the data is preserved. This allows you to save the entire state of a PDF generation task to a file or database.

    // Assuming pdfg is an initialized *wkhtmltopdf.PDFGenerator
    jsonData, err := pdfg.ToJSON()
    if err != nil {
    	// handle error
    }
    // jsonData now contains the full representation, including Base64 encoded page data
  11. Set the path to the wkhtmltopdf binary

    master

    If the generator cannot find the wkhtmltopdf executable automatically, or if you want to use a specific version, use SetPath(path) to define the absolute path to the binary. This setting is global and cached.

    // Set the path manually if auto-detection fails
    // or if you want to use a specific installation.
    // This must be called before Create().
    // Note: This is a global setting.
    // wkhtmltopdf.SetPath("/usr/local/bin/wkhtmltopdf")
  12. Restore a PDFGenerator from JSON with NewPDFGeneratorFromJSON()

    master

    The NewPDFGeneratorFromJSON(jsonReader io.Reader) function creates a new *PDFGenerator instance and restores all settings and pages from a JSON source.

    This function is designed to work with JSON byte slices previously created using the ToJSON() method. It correctly handles both standard Page inputs (via InputFile) and PageReader inputs (by decoding the embedded Base64 data back into readers).

    import (
    	"bytes"
    	"github.com/SebastiaanKlippert/go-wkhtmltopdf"
    )
    
    // Assuming jsonData was obtained from pdfg.ToJSON()
    jsonReader := bytes.NewReader(jsonData)
    
    pdfg, err := wkhtmltopdf.NewPDFGeneratorFromJSON(jsonReader)
    if err != nil {
    	// handle error
    }
    // pdfg is now a fully restored PDFGenerator ready for use