Adding an header to a generated PDF

I’m trying to add a header to my PDF but it is never getting rendered (even though the PDF is).
I’ve tried:

PdfGenerator.generate_binary!(no_sandbox: true, shell_params: ["--header-html", "../agreement.html"])
and
PdfGenerator.generate_binary!(no_sandbox: true, shell_params: ["--header-html", "#{read_file("../agreement.html")}"])

The library for PdfGenerator is https://github.com/gutschilla/elixir-pdf-generator
Am I doing something wrong here?

As this is wrapper over wkhtmltopdf then have you tried reading it’s docs?

Yap, the first thing I did. They just mention Headers and footers can also be supplied with HTML documents. As an example one could specify --header-html header.html, which is what I’ve tried to do, I think.

Try to add the html as a string. If you have a file you must create a Endpoint for that file.

Thanks for your input.
I’ve already tried adding the HTML as a string, but it also doesn’t seem to work:

PdfGenerator.generate_binary!(no_sandbox: true, shell_params: ["--header-html", "<!DOCTYPE html><html><body>ola 123</body></html>"])

I’m not sure I understand what you mean by creating an endpoint. I do in fact have an HTML file that I want to render as the header.

Try something like this for example:

PdfGenerator.generate("<html><body>body</body></html>",
      page_size: "A4",
      shell_params: ["--header-html", "<!DOCTYPE html><html><body>header</body></html>"]
    )

It doesn’t work (still generates without the header), it seems similar to the solution I tried above :thinking:

https://wkhtmltopdf.org/usage/wkhtmltopdf.txt - says that this param must be url.

Try this one:

PdfGenerator.generate("<html><body>body</body></html>",
      page_size: "A4",
      shell_params: ["--header-html", "https://google.com"]
    )

I think it can either be an URL or the html template file. I’ve tried with the google URL as well, but still no luck. I wonder if it’s a problem with the elixir-pdf-generator library.

--header-html accepts only url. Otherwise, you will get the following error:

Error: --header-html should be a URL and not a string containing HTML code.

The following code will generate a PDF file with the provided header:

tmp_dir = System.tmp_dir!()
header = Path.join(tmp_dir, "header.html")

File.write!(header, "<!DOCTYPE html><html><body><h1>header</h1></body></header>")

PdfGenerator.generate("<!DOCTYPE html><html><body><p>body</p></body></html>",
  page_size: "A4",
  shell_params: ["--header-html", "file://#{header}"]
)

As you can see, <!DOCTYPE html> is required in your input as well, not only header.

Thanks for the input!
Did it work for you? Curiously, I got the exact same result, just the body being rendered :thinking:
I’m running this code inside docker so I’m passing the no_sandbox: true flag and using generate_binary! followed by writing to a file, but I don’t think that should be why the header keeps being ignored.

PdfGenerator.generate_binary!("<!DOCTYPE html><html><body><p>body</p></body></html>",                                                                                                                      
   no_sandbox: true,                                                                                                                                                                                        
   page_size: "A4",                                                                                                                                                                                         
   shell_params: ["--header-html", "file://#{header}"]                                                                                                                                                      
)                                                                                                                                                                                                          
|> (&File.write("#{pdf_path}.pdf", &1)).()

It works with your call and parameters for me as well:

tmp_dir = System.tmp_dir!()

header = Path.join(tmp_dir, "header.html")
File.write!(header, "<!DOCTYPE html><html><body><h1>header</h1></body></header>")

content =
  PdfGenerator.generate_binary!(
    "<!DOCTYPE html><html><body>body</body></header>",
    no_sandbox: true,
    page_size: "A4",
    shell_params: ["--header-html", "file://#{header}"]
  )

File.write("out.pdf", content)

# $ wkhtmltopdf --version
# wkhtmltopdf 0.12.6 (with patched qt)

Here is a result:

You can inspect the executed command by running the following code before:

:dbg.tracer()
:dbg.p(:all, :c)
:dbg.tpl(System, cmd, :x)

Ok, so it seems like it’s a problem with wkhtmltopdf on my side. I’m currently running on version 0.12.5 but without the patched QT, which is the reason why it doesn’t work!! I’m running inside docker with alpine, so wkhtmltopdf is installed with a Dockerfile through RUN apk add wkhtmltopdf. Do you know if there’s a way to specify that I wan’t the QT patched version, or is it not available yet like this?

Unfortunately not, the only two available options are:

  • wkhtmltopdf 0.12.5 from v3.12,
  • wkhtmltopdf 0.12.6 from edge.

But they don’t include the desired patch. I think that you have to build this manually in your Dockerfile (preferably as an independent layer) and later copy it to your final image. I have never used this tool before so I can’t help you much with this.

1 Like

All right, will try to do that. Thanks so much for helping me spot the issue!