adrg / go-wkhtmltopdf

Handcrafted Go bindings for wkhtmltopdf and high-level HTML to PDF conversion interface
https://pkg.go.dev/github.com/adrg/go-wkhtmltopdf
MIT License
249 stars 21 forks source link

Inconsistent pdf formatting and output #29

Closed chilarai closed 2 years ago

chilarai commented 2 years ago

I am using the code below to generate my pdf using the library. The code executes appropriately. However, most of the time I lose my HTML formatting or even data in many cases. What could be the issue? Could this be memory related?

Note: My HTML has some css and js

package dummy

import (
    "code/common"
    "log"
    "os"

    pdf "github.com/adrg/go-wkhtmltopdf"
)

func GeneratePdf(filename string) {

    // Initialize library.
    if err := pdf.Init(); err != nil {
        log.Println(err)
    }
    defer pdf.Destroy()

    // Create object from file.
    object, err := pdf.NewObject("./inputhtml/uc_" + filename + ".html")
    if err != nil {
        log.Println(err)
    }

    // Create object from URL.
    object2, err := pdf.NewObject("./inputhtml/tc_" + filename + ".html")
    if err != nil {
        log.Println(err)
    }

    // Create object from reader.
    object3, err := pdf.NewObject("./inputhtml/invoice_" + filename + ".html")
    if err != nil {
        log.Println(err)
    }

    object4, err := pdf.NewObject("./inputhtml/feru_" + filename + ".html")
    if err != nil {
        log.Println(err)
    }

    // Create converter.
    converter, err := pdf.NewConverter()
    if err != nil {
        log.Println(err)
    }
    defer converter.Destroy()

    // Add created objects to the converter.
    converter.Add(object)
    converter.Add(object2)
    converter.Add(object3)
    converter.Add(object4)

    // Set converter options.
    converter.Title = "Out documents"
    converter.PaperSize = pdf.A4
    converter.Orientation = pdf.Portrait
    converter.MarginTop = "1cm"
    converter.MarginBottom = "1cm"
    converter.MarginLeft = "10mm"
    converter.MarginRight = "10mm"

    // Convert objects and save the output PDF document.
    outFile, err := os.Create(common.CONST_TMPPDF_FOLDER + "out_" + filename + ".pdf")
    if err != nil {
        log.Println(err)
    }
    defer outFile.Close()

    if err := converter.Run(outFile); err != nil {
        log.Println(err)
    }
}
chilarai commented 2 years ago

I figured out that if I pass bytes.NewBuffer in converter.Run() instead of outFile, I get a consistent output. So I changed the pdf generation block from

// Convert objects and save the output PDF document.
outFile, err := os.Create(common.CONST_TMPPDF_FOLDER + "out_" + filename + ".pdf")
if err != nil {
log.Println(err)
}
defer outFile.Close()

if err := converter.Run(outFile); err != nil {
log.Println(err)
}

TO

return converter.Run(out)

...

// Do Remember to serve the file later
w.Header().Set("Content-Disposition", "attachment; filename=download.pdf")
w.Header().Set("Content-Type", "application/pdf")
if _, err := io.Copy(w, out); err != nil {
    http.Error(w, err.Error(), http.StatusInternalServerError)
}

as described in https://github.com/adrg/go-wkhtmltopdf/blob/master/examples/http-server/main.go. Also, I created a new server to avoid thread related issues in pdf generation

adrg commented 2 years ago

Hi @chilarai. Did that solve the problems your were having? Can this issue be closed?

chilarai commented 2 years ago

Yes thats it. Thanks