go-wkhtmltopdf
go-wkhtmltopdf copied to clipboard
Creating PDF files in a loop
func main() { for _, v := range []string{"import1.pdf", "import2.pdf", "import3.pdf"} { CreatePDFFile("header.html", "footer.html", "content.html", v) } }
func CreatePDFFile(header, footer, content, output string) error { // Initialize library. if err := pdf.Init(); err != nil { log.Print("fail init", err)
return err
}
defer pdf.Destroy()
//Insert the content inside the template
// Create object from URL.
object, err := pdf.NewObject(content)
if err != nil {
log.Print("fail new object", err)
return err
}
defer object.Destroy()
object.Header.CustomLocation = header
object.Footer.CustomLocation = footer
converter, err = pdf.NewConverter()
if err != nil {
log.Print("fail new converter", err)
return err
}
defer converter.Destroy()
converter.PaperSize = pdf.Letter
// Add created objects to the converter.
converter.Add(object)
// Convert objects and save the output PDF document.
outFile, err := os.Create(output)
if err != nil {
log.Print("fail create", err)
return err
}
defer outFile.Close()
// Run converter.
if err := converter.Run(outFile); err != nil {
log.Print("fail run", err)
return err
}
return nil
}
Runing this code will create 1 valid file, the first one and two invalid files.
Hi @zaky
The library needs to be initialized only once, when the application starts. This should work fine:
package main
import (
"log"
"os"
pdf "github.com/adrg/go-wkhtmltopdf"
)
func main() {
// Initialize library.
if err := pdf.Init(); err != nil {
log.Fatal(err)
}
defer pdf.Destroy()
for _, v := range []string{"import1.pdf", "import2.pdf", "import3.pdf"} {
if err := CreatePDFFile("header.html", "footer.html", "content.html", v); err != nil {
log.Fatal(err)
}
}
}
func CreatePDFFile(header, footer, content, output string) error {
// Create object from URLs.
object, err := pdf.NewObject(content)
if err != nil {
return err
}
defer object.Destroy()
object.Header.CustomLocation = header
object.Footer.CustomLocation = footer
// Create converter.
converter, err := pdf.NewConverter()
if err != nil {
return err
}
defer converter.Destroy()
converter.PaperSize = pdf.Letter
// Add created objects to the converter.
converter.Add(object)
// Convert objects and save the output PDF document.
outFile, err := os.Create(output)
if err != nil {
return err
}
defer outFile.Close()
// Run converter.
if err := converter.Run(outFile); err != nil {
return err
}
return nil
}
Actually the code is part of a web server. What I fount is that if I put the pdf.init/pdf.destroy in main the first request is working fine but not the following requests. From the second request the server jut stock.
For usage inside goroutines
see the Basic web page to PDF conversion server or the Configurable web page to PDF conversion server examples. Issue https://github.com/adrg/go-wkhtmltopdf/issues/3 is also relevant.
The library must be initialized on the main thread and the conversion must be performed on the main thread as well. This is a known limitation of wkhtmltox
, not of this package.
I suppose, as mentioned in previous comment, this code block
func init() {
// Set main function to run on the main thread.
runtime.LockOSThread()
}
in general cases prevents situation with library stuck