gutschilla / elixir-pdf-generator Goto Github PK
View Code? Open in Web Editor NEWCreate PDFs with wkhtmltopdf or puppeteer/chromium from Elixir.
License: MIT License
Create PDFs with wkhtmltopdf or puppeteer/chromium from Elixir.
License: MIT License
https://github.com/gutschilla/elixir-pdf-generator/blob/master/README.md#optional-dependencies
In order for us to use pdf_generator
with wkhtmltopdf
on Gigalixir using Releases, I have to use the following configuration in order for my app to be able to take advantage of wkhtmltopdf
.
config :pdf_generator,
command_prefix: ["xvfb-run", "-a"],
delete_temporary: true
Gigalixir runs with the Heroku Cedar-14 stack. This stack includes wkhtmltopdf
, but I'm having a challenging time getting pdf_generator
installed in "headless chrome" mode since I can't globally install npm
modules. I took a break from exploring options with custom buildpacks and will hopefully discover a way to get pdf_generator
to work with headless Chrome eventually since this would provide several advantages to our users.
Hello Martin,
Do you think it would be possible to add some examples what can be
done via elixir-pdf-generator?
For example like in http://www.fpdf.org/en/tutorial/tuto4.htm at the Demo
link. It does not have to be as fancy as in FPDF by the way, just some
example gallery e. g. 1-5 examples of what can be done to get
a "head start" with elixir-pdf-generator. I learn best from simple examples,
already have been using ruby for a long time, now also learning elixir
slowly.
Using pdfgenerator 0.4.0
on Heroku (heroku-16 stack), inside a Phoenix 1.4.1 app. Works fine locally.
Trying to run
view_as_string
|> PdfGenerator.generate_binary!(
delete_temporary: true,
shell_params: @pdf_options
)
@pdf_options are
[
"--print-media-type",
"--page-size",
"Letter",
"--margin-top",
"15",
"--margin-right",
"5",
"--margin-bottom",
"5",
"--margin-left",
"5",
"--footer-right",
"[page] of [toPage]",
"--footer-font-size",
"8",
"--footer-left",
"Created: [date]"
]
I get the following output to the logs
18:31:16 app[web.1]: [> ] 0%
18:36:01 app[web.1]: [============================================================] 100%
18:36:01 app[web.1]: [============================================================] Object 1 of 1
18:36:01 app[web.1]: [============================================================] Object 1 of 1
18:36:01 app[web.1]: Printing pages (6/6)
18:36:01 app[web.1]: [> ] Preparing
18:36:01 app[web.1]: Exit with code 1 due to network error: TimeoutError
So it errors out after a near 5 minute wait?
Interestingly if I make delete_temporary: true
I can see the generated file in the tmp
directory after the error has been displayed.
I have the build packs as per the order shown on the Getting Started, and they appear to be installing correctly as per the build logs so I'm at a loss as to what might be wrong here?
Thanks.
For some reason, when running on Windows, it always tries to use xvfb-run
, which obviously fails. I'm not entirely sure if this is a bug or I'm missing something.
I'm using:
> iex --version
IEx 1.9.2 (compiled with Erlang/OTP 20)
> wkhtmltopdf --version
wkhtmltopdf 0.12.5 (with patched qt)
Erlang, Elixir and wkhtmltopdf are all on my path. When running the example, I get:
iex(2)> PdfGenerator.generate(html, page_size: "A5", command_prefix: nil)
[debug] {"xvfb-run", ["-a", "c:/Program Files/wkhtmltopdf/bin/wkhtmltopdf.exe", "--page-size", "A5", "C:\\Users\\strij\\AppData\\Local\\Temp/8PnBbvX0.html", "C:\\Users\\strij\\AppData\\Local\\Temp/8PnBbvX0.pdf"]}
** (ErlangError) Erlang error: :enoent
(elixir) lib/system.ex:791: System.cmd("xvfb-run", ["-a", "c:/Program Files/wkhtmltopdf/bin/wkhtmltopdf.exe", "--page-size", "A5", "C:\\Users\\strij\\AppData\\Local\\Temp/8PnBbvX0.html", "C:\\Users\\strij\\AppData\\Local\\Temp/8PnBbvX0.pdf"], [stderr_to_stdout:
true])
(pdf_generator) lib/pdf_generator.ex:141: PdfGenerator.generate/2
Can i specify the chrome path?
I need to use the node modules however the package searches for one on the highest level, not on assets.
Is there a way to pass in other wkhtmltopdf commands such as page-height and page-width, margin-bottom etc? If so, wonder if we should add to readme?
The only way I could make a image appear on pdf is passing the absolute path, I thinks this is the way Wkthmltopdf works according this issue.
So I need to do that:
<header>
<img style="display: block; margin: 0 auto;" src="file:///Users/root/GitHub/projects/my-app/web/static/images/logo.png" alt="" />
</header>
Is there a way of use relative path ?
I'm using the same style I had on my other ruby project and is not being applied. Any idea why?
What do you think about embedding the used stuff from misc_random
? It just a tiny thing to be an extra dependency and also will avoid the problem on distillery and exrm.
In the README it says you can pass :command_prefix
to :pdf_generator
config. However from code in tag v0.3.3 you can see that :command_prefix
option is not actually implemented yet. I didn't know that option wasn't actually advertised in hex docs ... I was reading the README in master and in v0.3.0 branches.
Are you planning on pushing that option to Hex anytime soon ?
Hello all!
I've already posted this issue in this Elixir Forum post, where I was advised to open an issue on Github: https://elixirforum.com/t/how-to-configure-pdf-generator-to-use-local-installation-of-chrome-headless-render-pdf-and-puppeteer/28714
Maybe I'll some guidance here too. But here is a copy just in case:
I managed to use pdf_generator with chrome-headless-render-pdf and puppeteer installed globally. Now I'd rather have both packages installed locally, however I couldn't find a way to make it work.
I tried to install both packages within the /assets
folder by running the npm install chrome-headless-render-pdf puppeteer
command.
This did not work as pdf_generator expect chrome-headless-render-pdf
to be in _build/dev/lib/pdf_generator/priv/node_modules/chrome-headless-render-pdf/dist/cli/chrome-headless-render-pdf.js
After reading the README.md, and implementing the instructions for a local chrome install, I still get the same error.
Basically what I did is:
{:pdf_generator, ">=0.6.0", compile: "make chrome"}
to mix.exs
make priv/node_modules
which returns me this error make: *** No rule to make target 'priv/node_modules'. Stop.
cd priv && npm install
and rerun the above mentioned command, which still gets me the same make error.mix deps.get
and mix phx.server
which return me this error make: *** No rule to make target 'chrome'. Stop. ** (Mix) Could not compile dependency :pdf_generator, "make chrome" command failed. You can recompile this dependency with "mix deps.compile pdf_generator", update it with "mix deps.update pdf_generator" or clean it with "mix deps.clean pdf_generator"
with none of the mentioned command working.Any tipps?
I have GNU Make 4.1
, nodejs v12.14.1
, npm 6.13.4
and Elixir 1.10.0
.
This may just be me doing things incorrectly on heroku but I thought I'd make an issue since other coders will probably hit this. I added wkhtmltopdf and pdftk buildpacks to my heroku setup,
https://github.com/HashNuke/heroku-buildpack-elixir
https://github.com/gjaldon/phoenix-static-buildpack
https://github.com/dscout/wkhtmltopdf-buildpack.git
https://github.com/fxtentacle/heroku-pdftk-buildpack.git
The first two are standard phoenix+elixir buildpacks which work fine. For some reason though this is still failing while using heroku. It doesn't seem to report an error in the logger but it was my PDFgenerator branch that broke heroku. Any ideas on this?
Hi, any tips for compiling on Win10?
I've changed to:
{:pdf_generator, "~> 0.6.2", compile: "mingw32-make chrome"}
But get *** No rule to make target..
when running mix deps.compile pdf_generator
Which I think means it cannot find a makefile (I could be wrong since I know nothing about such matters)
The pdf_generator directory in my project doesn't contain the makefile, not sure if I should expect it to!
Does this local compilation of headless chrome allow deploy to Heroku / Gigalixir? I'm struggling to find a package for pdf conversion that I can deploy (they all run locally of course, but that's of no practical use :) ). A recipe for this would be very helpful.
wkhtmltopdf tool can generate PDF by given URL. E.g.
wkhtmltopdf http://example.cpm google.pdf
@gutschilla How can I do it with this library?
Hi @gutschilla,
first of all, thanks for this library which has been generating many PDFs for us so far. :-)
There's a breaking change in the newest version, which I'm not sure was intended: Instead of forwarding shell_params
as first argument to wkhtmltopdf, they are now put last. This breaks "global options" like --margin-right
, which have to be put right after wkhtmltopdf
:
Name
wkhtmltopdf - html to pdf converter
Synopsis
wkhtmltopdf [GLOBAL OPTION]... [OBJECT]... <output file>
Hi, I am trying to work through the instructions in the README for setting up a PDF generator on heroku.
My list of buildpacks looks like this
1. https://github.com/fxtentacle/heroku-pdftk-buildpack.git
2. https://github.com/dscout/wkhtmltopdf-buildpack.git
3. https://github.com/HashNuke/heroku-buildpack-elixir
4. heroku/ruby
However it looks like it is failing on the very first one.
remote: Building source:
remote:
remote: -----> heroku-pdftk-buildpack app detected
remote: cp: cannot stat 'binaries-heroku-16/*': No such file or directory
remote: ! Push rejected, failed to compile heroku-pdftk-buildpack app.
remote:
remote: ! Push failed
remote: Verifying deploy...
remote:
remote: ! Push rejected to my-app.
remote:
Has anyone suffered a similar problem/ have any pointers?
As @hugomaiavieira pointed out, Porcelain doesn't seem to be maintained since a while and throws up warning messages on compilation. This dependency dates back to the roots of PdfGenerator
when I was too lazy hesitant to use the Ports
module directly. Which wasn't exactly documented in a great way (https://hexdocs.pm/elixir/1.0.5/Port.html#summary).
Anyways, to get things going, I'll remove Porcelain in 0.5.0 using Ports.
When we use the :command_prefix
option to run wkhtmltopdf
within xvfb
, we found that when we run generate!
multiple times in rapid succession, it will eventually fail showing a Xvfb failed to start
error.
We were able to reproduce the failure directly at the command line and got this more verbose output from xvfb.
Fatal server error:
(EE) Server is already active for display 99
If this server is no longer running, remove /tmp/.X99-lock
and start again.
The -a
option for xvfb-run
allows it to look for a free server number rather than assuming 99, and using this resolved our intermittent failure.
But, because of the way the command is formed for Porcelain.exec
, it's not possible for us to just include the -a
flag in the :command_prefix
config.
We're interested in submitting a PR for this, but I wanted to make sure that would be welcome and see if you had any thoughts on how it should be handled.
Some ideas so far:
:command_prefix
config value on the first whitespace and assume anything after the split are arguments that are similarly prepended to the arguments returned by make_command_tuple
:command_prefix_arguments
config option and prepend those to the second element returned by make_command_tuple
Hi,
This is what I get in production, when I try to generate PDF from HTML template.
** (exit) an exception was raised:
** (UndefinedFunctionError) function Misc.Random.string/0 is undefined (module Misc.Random is not available)
Misc.Random.string()
(pdf_generator) lib/pdf_generator.ex:111: PdfGenerator.generate/2
I've tried adding {:misc_random, ">=0.2.6"} to my mix.exs file and I've added misc_random to applications but the error is still the same.
Elixir 1.3.2
Erlang/OTP 19
Thanks.
Attempted to run the tutorial in a simple app - got this message.
Looks like everything is being pulled in, but the Alias from Misc.Random to Random isn't being called.
Hi I am switching a project from Ruby to elixir. previously I was using PDFKit. It had a few helpers for including stylesheets that I don't know how to recreate with elixir-pdf-generator.
My html page is shown as both HTML and PDF. I have a stylesheet that is served from the same server as the html page.
In my html is this line
<link rel="stylesheet" href="/stylesheets/licence.css" media="screen" title="no title" charset="utf-8">
How do I get this file included in the generated pdf.
I think the answer is to convert the relative filepath into an absolute one.
I'm not sure if I should convert it to the hosted location of the stylesheet or the location in the server file structure.
uri = %URI{host: request.host, scheme: "http", port: request.port, path: "/stylesheets/licence.css"}
html = String.replace(html, "href=\"/stylesheets/licence.css\"", "href=\"uri\"")
OR
uri = %URI{host: request.host, scheme: "http", port: request.port, path: "/stylesheets/licence.css"}
html = String.replace(html, "href=\"/stylesheets/licence.css\"", "href=\"#{Application.app_dir(:my_app)}/stylesheets/licence.css\"")
Any pointers would be greatly apprechiated
I am working on Elixir 1.6.6, and any pdf_generator version above 0.4.0 is throwing me this error. What might be the issue here?
[error] #PID<0.826.0> running StarterWeb.Endpoint (cowboy_protocol) terminated Server: localhost:4000 (http) Request: GET /api/v1/resume/pdf/save ** (exit) an exception was raised: ** (FunctionClauseError) no function clause matching in System.cmd/3 (elixir) lib/system.ex:609: System.cmd(nil, ["/var/folders/01/4lmfmjf1073c57s7gg7mxf6h0000gn/T/CV_Shijith_K_20190709.pdf", "output", "/var/folders/01/4lmfmjf1073c57s7gg7mxf6h0000gn/T/6BHzmlex.pdf", "owner_pw", "1234", "user_pw", "9Om7ymGMurtOiFsn", "encrypt_128bit", "allow", "Printing", "CopyContents"], [stderr_to_stdout: true]) (pdf_generator) lib/pdf_generator.ex:255: PdfGenerator.encrypt_pdf/3 (pdf_generator) lib/pdf_generator.ex:138: PdfGenerator.generate/2
I've latest nodejs version 15.14.0. I've created new phoenix project by mix phx.new hello --no-webpack
.
Then, I created assets folder.
Inside the assets, I run npm install chrome-headless-render-pdf puppeteer
. And added { :pdf_generator, ">=0.6.2", compile: "make chrome" }
in mix.exs.
mix deps.get pdf_generator
- It's working fine
mix deps.compile pdf_generator
- When i run this command. I'm getting this error
make: *** No rule to make target 'chrome'. Stop. ** (Mix) Could not compile dependency :pdf_generator, "make chrome" command failed. You can recompile this dependency with "mix deps.compile pdf_generator", update it with "mix deps.update pdf_generator" or clean it with "mix deps.clean pdf_generator"
As mentioned ReadMD, I've changed the {:pdf_generator, "~> 0.6.2", github: "gutschilla/elixir-pdf-generator", compile: "make chrome"}
it in mix.exs. After that, I've cleaned the deps and mix deps.get and I've compiled the code by mix deps.compile pdf_generator
. Now, I'm getting this error make: *** No rule to make target 'config/prod.exs', needed by '_build/prod'. Stop. ** (Mix) Could not compile dependency :pdf_generator, "make chrome" command failed. You can recompile this dependency with "mix deps.compile pdf_generator", update it with "mix deps.update pdf_generator" or clean it with "mix deps.clean pdf_generator"
I've tried another one method also, removed make chrome from the mix.exs as { :pdf_generator, ">=0.6.0" }
. And installed chromium apt-get install -y chromium-chromedriver
. Now, mix deps.compile pdf_generator
was working fine. But, when i run PdfGenerator.generate(url, generator: :chrome, prefer_local_executable: true)
. I'm getting this error {:error, {:generator_failed, "node:internal/modules/cjs/loader:927\n throw err;\n ^\n\nError: Cannot find module '/home/yasir/hello/_build/dev/lib/pdf_generator/priv/node_modules/chrome-headless-render-pdf/dist/cli/chrome-headless-render-pdf.js'\n at Function.Module._resolveFilename (node:internal/modules/cjs/loader:924:15)\n at Function.Module._load (node:internal/modules/cjs/loader:769:27)\n at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:76:12)\n at node:internal/main/run_main_module:17:47 {\n code: 'MODULE_NOT_FOUND',\n requireStack: []\n}\n"}}
It's Working with this configuration for me.
Add {:pdf_generator, "~> 0.6.2", github: "gutschilla/elixir-pdf-generator"} in to mix.exs
then run mix deps.clean pdf_generator && mix deps.get pdf_generator && mix deps.compile && mix deps.compile pdf_generator
install chromium apt-get install -y chromium-chromedriver
I was using no-webpack project. So, I've created assets
folder in root project directory
cd assets
and npm install chrome-headless-render-pdf puppeteer
Now go back to project root directory. Go into the deps/pdf_generator/
then run make priv/node_modules
. Finally, pdf generation working with this steps.
What i was doing wrong in 1,2 and 3 procedure?
In 4th procedure, why i need run that make command inside the deps(Correct me, if I am doing anything wrong).
When I perform a hot code upgrade on a running server, the elixir-pdf-generator fails whenever it is called with the following error:
(Porcelain.UsageError) Looks like the :porcelain app is not running. Make sure you've added :porcelain to the list of applications in your mix.exs.
I've added :porcelain to mix.exs as well as added it to rel/config.exs
under applications, but neither solve the problem. Manually restarting the server works just fine and PDFGenerator will work correctly without any porcelain errors. However, whenever I perform a hot code upgrade, it will generate this error.
hi there
is it possible to use this with Phoenix and specify routes that combine to generate a PDF?
thankyou
Hey, do you have plans on offering a way to generate pdfs on the fly?
I want to use it for my phoenix framework app without saving the pdf file. I want the generated pdf to be in a variable and display it in the browser.
I'm having problems running this without installing wkhtmltopdf
. The documentation says that one needs either wkhtmltopdf
or chromium
, so I installed chromium
.
However, when I start the application with mix phx.server
, the following error occurs:
** (Mix) Could not start application pdf_generator: PdfGenerator.start(:normal, []) returned an error: shutdown: failed to start child: PdfGenerator.PathAgent
** (EXIT) an exception was raised:
** (RuntimeError) wkhtmltopdf executable was not found on your system
(pdf_generator) lib/pdf_generator_path_agent.ex:76: PdfGenerator.PathAgent.maybe_raise/3
(pdf_generator) lib/pdf_generator_path_agent.ex:69: PdfGenerator.PathAgent.raise_or_continue/1
(pdf_generator) lib/pdf_generator_path_agent.ex:37: PdfGenerator.PathAgent.init_opts/1
(elixir) lib/agent/server.ex:8: Agent.Server.init/1
(stdlib) gen_server.erl:374: :gen_server.init_it/2
(stdlib) gen_server.erl:342: :gen_server.init_it/6
(stdlib) proc_lib.erl:249: :proc_lib.init_p_do_apply/3
So, is wkhtmltopdf
required when I only want to use chromium
as well?
I installed chromium
locally with:
npm install chrome-headless-render-pdf puppeteer
I added this to config/config.exs
:
config :pdf_generator,
use_chrome: true
And added :pdf_generator
to application
:
def application do
[
mod: {MyApp.Application, []},
extra_applications: [:logger, :runtime_tools, :pdf_generator]
]
end
Hey, I'm getting this error when trying to implement pdf_generator
into my phoenixframework app:
undefined function Random.string/0 (module Random is not available)
I tried putting
{:pdf_generator, "0.2.0"} AND {:misc_random, ">=0.2.5" }
into my mix.exs
but It didn't solve the problem. Also I load both modules into my application in the mix.exs
file.
Hi.
I have this problem when deploy my elixir project with docker, when I'm working in localhost I don't have problems, I'm using wkhtmltopdf and {:pdf_generator, ">=0.5.7"}
this is the error
22:47:37.725 [info] [alarm_handler: {:set, {:system_memory_high_watermark, []}}]
22:47:37.730 [info] Application pdf_generator exited: PdfGenerator.start(:normal, []) returned an error: shutdown: failed to start child: PdfGenerator.PathAgent
** (EXIT) an exception was raised:
** (RuntimeError) wkhtmltopdf executable was not found on your system
(pdf_generator) lib/pdf_generator_path_agent.ex:76: PdfGenerator.PathAgent.maybe_raise/3
(pdf_generator) lib/pdf_generator_path_agent.ex:69: PdfGenerator.PathAgent.raise_or_continue/1
(pdf_generator) lib/pdf_generator_path_agent.ex:37: PdfGenerator.PathAgent.init_opts/1
(elixir) lib/agent/server.ex:8: Agent.Server.init/1
(stdlib) gen_server.erl:374: :gen_server.init_it/2
(stdlib) gen_server.erl:342: :gen_server.init_it/6
(stdlib) proc_lib.erl:249: :proc_lib.init_p_do_apply/3
22:47:37.731 [info] [alarm_handler: {:clear, :system_memory_high_watermark}]
this is my dockerfile:
FROM elixir:1.9.1 as builder
ENV MIX_ENV=prod
RUN apt install curl \
&& curl -sL https://deb.nodesource.com/setup_12.x | bash - \
&& apt-get install -y nodejs \
&& apt-get install -y npm
RUN apt-get update && \
apt-get install -y --no-install-recommends wkhtmltopdf && \
rm -rf /var/lib/apt/lists/*
RUN mix local.hex --force \
&& mix local.rebar --force
...
help!
Hey,
I updated to wkhtmltopdf 0.12.6 and there seems to be this problem:
wkhtmltopdf/wkhtmltopdf#4926
or this
https://stackoverflow.com/questions/62315246/wkhtmltopdf-0-12-6-warning-blocked-access-to-file
The solution would be to pass the --enable-local-file-access flag, I tried to pass it as shell params but doesn't seem to work.
How should I pass it?
I am getting after some tweaking:
(MatchError) no match of right hand side value: {:error, {:generator_failed, "Loading page (1/2)\n[> ] 0%\r[==============> ] 24%\r"}}
The original full error is the following:
(MatchError) no match of right hand side value: {:error, {:generator_failed, "QStandardPaths: XDG_RUNTIME_DIR not set, defaulting to '/tmp/runtime-root'\nLoading page (1/2)\n[> ] 0%\r[======================> ] 37%\rWarning: Blocked access to file /tmp/qr_business_order_nEQx8vpXgWDbXAmN.png\nError: Failed to load about:blank, with network status code 301 and http status code 0 - Protocol "about" is unknown\n"}}
I fixed the XDG_RUNTIME_DIR part by setting it as an env var, and i fixed the 301 by not writing images to files and loading them, but rather passing them as base64 to the template.
The last piece is the error on the top, that I think the flag could fix, the flag might have fixed it all.
PDFtk cask has been removed from Homebrew as per this gist. The reason mentioned in the gist is quoted below.
This workaround install is necessary because PDFtk was pulled from homebrew-cask due to issues with it aggressively overwriting file permissions that could impact other installed libraries. See this homebrew-cask issue.
Please update the readme if you find this helpful.
Thank you
First, thanks for this package, super helpful.
I'm having an issue where I'm trying to generate a PDF from HTML. I'm using bbmustache to generate the HTML from a template and a set of tokens. My result is:
"<html>\n <body>\n <div>\n <p><strong>Booking ID: the booking id</strong></p>\n </div>\n </body>\n</html>\n"
When I pipe the result above into |> PdfGenerator.generate_binary!() |> (&File.write("#{pdf_path}.pdf", &1)).()
, it generates a PDF with the correct name and path, but it's completely blank. Any idea what could be causing this?
Thanks!
when generating the pdf, the text disappears.
I have this configuration:
Dockerfile:
ARG PUPPETEER_SKIP_DOWNLOAD=true
RUN npm -g install chrome-headless-render-pdf puppeteer
FROM alpine:3.11
RUN apk update && \
apk add --no-cache \
bash \
wkhtmltopdf=0.12.5-r0
mix.ex
{:pdf_generator, "~> 0.6.2"},
in the local environment it generates the PDFs correctly but when I deploy in production it creates them without text
From an answer to #19 I think of a new configuration avlue that cwds into the configured directory and calls wkhtmltopdf from there.
Hi!
Hex doesn't seem to have your latest version as stated on the readme. They seem to have 0.3.6
only.
I'm not sure if you were aware of this or not.
I'm relatively newbie in Elixir. I'm curious about why you setup an Agent for the elixir-pdf-generator.
Is it really necessary to depend on porcelain and goon(optional) to just call the underlying wkhtmltopdf
?
Is it possible to pass other wkhtmltopdf options like orientation ?
filename: "/somepath/store/pdffiles/test" # this should generate the file in /somepath/store/pdffiles/test.pdf
but instead it generated as:
/tmp/somepath/store/pdffiles/test.pdf
Actually even this file not exist, looks like need parent folder exists to generate.
rather than deal with wkhtmltopdf and flexbox, i've moved to chrome. the docs suggest this for using chrome-headless
config :pdf_generator,
use_chrome: true, # <-- make sure you installed node/puppeteer
prefer_system_executable: true # <-- set this if you installed the NPM dependencies globally
raise_on_missing_wkhtmltopdf_binary: false, # <-- so the app won't complain about a missing wkhtmltopdf
as best as i can tell, use_chrome: true
doesn't work, and prefer_system_executable: true
doesn't work in config.exs
i believe that config only works here, and like this:
|> PdfGenerator.generate_binary(
generator: :chrome,
prefer_system_executable: true
)
@gutschilla I got empty error message. How to get more details about error?
I am trying to use elixir-pdf-generator in my web app.
First I have tried to use it with wkhtmltopdf, but it seems it does not handle all css correctly
So, I am now using it with Chrome-headless/Puppeteer.
I have installed it according to:
Eventually, if you are using Phoenix and you would like to have your npm packages installed localy, within the
/assets/node_modules
directory, simply runnpm install chrome-headless-render-pdf puppeteer
withinassets/node_modules
and passprefer_local_executable: true
option when generating the PDF like this:PdfGenerator.generate(url, generator: :chrome, prefer_local_executable: true)
Bit if I try it with an existing url, I get:
[debug] {"/usr/local/bin/node", ["/home/peter/bw/_build/dev/lib/pdf_generator/priv/node_modules/chrome-headless-render-pdf/dist/cli/chrome-headless-render-pdf.js", "--url", "http://localhost:4000/factuur/test", "--pdf", "/tmp/MlUkqisz.pdf", "--paper-width", "8.26772", "--paper-height", "11.695"]}
{:error,
{:generator_failed,
"internal/modules/cjs/loader.js:883\n throw err;\n ^\n\nError: Cannot find module '/home/peter/bw/_build/dev/lib/pdf_generator/priv/node_modules/chrome-headless-render-pdf/dist/cli/chrome-headless-render-pdf.js'\n at Function.Module._resolveFilename (internal/modules/cjs/loader.js:880:15)\n at Function.Module._load (internal/modules/cjs/loader.js:725:27)\n at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:72:12)\n at internal/main/run_main_module.js:17:47 {\n code: 'MODULE_NOT_FOUND',\n requireStack: []\n}\n"}}
Any ideas?
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")}"])
Am I doing something wrong here?
Hi!
I have added use_chrome: true
as well as raise_on_missing_wkhtmltopdf_binary: false
to config.exs
, however, I still always get the warning [warn] wkhtmltopdf executable was not found on your system
.
Could someone please let me know how to remove this warning?
Thanks!
Hi.
For bigger teams adding wkhtmltopdf to a small part of an application requires all team members to install it to be able to run the phoenix server.
I suggest this be changed to a warn on app start and a raised error on usage instead of simply stopping the application from starting alltogether.
porcelain 2.0.2 is in the _build and it certainly has exec/3.
the full stacktrace is below.
Any thoughts on what I did wrong would be appreciated.
thanks, -doug.
versions: Phoenix v1.2.1, Elixir 1.3.2, Erlang 19
This is a new phoenix app with these configs:
def application do
[mod: {FlyerMaker, []},
applications: [:phoenix, :phoenix_pubsub, :phoenix_html, :cowboy, :logger, :gettext,
:phoenix_ecto, :postgrex, :pdf_generator]]
end
# Type `mix help deps` for examples and options.
defp deps do
[{:phoenix, "~> 1.2.1"},
{:phoenix_pubsub, "~> 1.0"},
{:phoenix_ecto, "~> 3.0"},
{:postgrex, ">= 0.0.0"},
{:phoenix_html, "~> 2.6"},
{:phoenix_live_reload, "~> 1.0", only: :dev},
{:gettext, "~> 0.11"},
{:cowboy, "~> 1.0"},
{:pdf_generator, ">=0.3.0"}]
end
➜ flyer_maker git:(master) ✗ iex -S mix
Erlang/OTP 19 [erts-8.0.2] [source] [64-bit] [smp:8:8] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]
Compiling 12 files (.ex)
Generated flyer_maker app
Interactive Elixir (1.3.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> html = "<html><body><p>Hi there!</p></body></html>"
"<html><body><p>Hi there!</p></body></html>"
iex(2)> { :ok, filename } = PdfGenerator.generate html, page_size: "A5", open_password: "s3cr3t"
** (FunctionClauseError) no function clause matching in Porcelain.exec/3
(porcelain) lib/porcelain.ex:127: Porcelain.exec(nil, ["/var/folders/fh/p_0tnm5j46lc5n00hkhzyzyw0000gn/T/zaa6W1Lz.pdf", "output", "/var/folders/fh/p_0tnm5j46lc5n00hkhzyzyw0000gn/T/iY7m1x9n.pdf", "owner_pw", "YEYmQWQv0jGdytPT", "user_pw", "s3cr3t", "encrypt_128bit", "allow", "Printing", "CopyContents"], [])
(pdf_generator) lib/pdf_generator.ex:160: PdfGenerator.encrypt_pdf/3
iex(2)>
Related to #56
I'm getting this error on linux server:
(elixir) lib/system.ex:621: System.cmd(nil, ["/opt/app/lib/pdf_generator-0.6.0/priv/node_modules/chrome-headless-render-pdf/dist/cli/chrome-headless-render-pdf.js", "--url", "file:///tmp/0wolmM04.html", "--pdf", "/tmp/0wolmM04.pdf", "--paper-width", "8.26772", "--paper-height", "11.695", "--dpi", "300"], [stderr_to_stdout: true])
In my case, I'm switching from wkhtmltopdf
which was working but with some issues in the layout to chrome-headless
. I'm sure that chromdriver, nodejs, chrome-headless-render-pdf and, puppeteer are being installed as well.
RUN apk update && \
apk upgrade --no-cache && \
apk add --no-cache \
...
nodejs \
npm \
chromium \
chromium-chromedriver
RUN npm -g install chrome-headless-render-pdf puppeteer
config :pdf_generator,
use_chrome: true,
prefer_system_executable: true,
raise_on_missing_wkhtmltopdf_binary: false
PdfGenerator.generate(
html,
generator: :chrome,
prefer_system_executable: true,
page_size: "A4",
shell_params: ["--dpi", "300"],
no_sandbox: true
)
Yeap, I'm using mix release.
Hi,
I was trying to get the generator to return a pdf file with a custom name passed via shell_params: ["--title", "custom_filename"]
, but it seems to be impossible due to this:
pdf_file = random_filebase <> ".pdf"
...
case status do
0 ->
case Keyword.get options, :open_password do
nil -> { :ok, pdf_file }
user_pw -> ...
end
_ -> { :error, error }
end
If I'm reading this right if the pdf generation was successful, the generator returns the filename assigned long before any options were passed to wkhtmltopdf...
This project is using wkhtmltopdf
, so we don't have headless Chrome installed locally or in CI.
Starting the application returns the following error:
** (Mix) Could not start application pdf_generator: PdfGenerator.start(:normal, []) returned an error: shutdown: failed to start child: PdfGenerator.PathAgent
** (EXIT) an exception was raised:
** (FunctionClauseError) no function clause matching in IO.chardata_to_string/1
(elixir) lib/io.ex:461: IO.chardata_to_string(nil)
(elixir) lib/file.ex:214: File.exists?/2
(pdf_generator) lib/pdf_generator_path_agent.ex:63: PdfGenerator.PathAgent.raise_or_continue/1
(pdf_generator) lib/pdf_generator_path_agent.ex:37: PdfGenerator.PathAgent.init_opts/1
(elixir) lib/agent/server.ex:8: Agent.Server.init/1
(stdlib) gen_server.erl:374: :gen_server.init_it/2
(stdlib) gen_server.erl:342: :gen_server.init_it/6
(stdlib) proc_lib.erl:249: :proc_lib.init_p_do_apply/3
It appears that File.exists?(path)
throws when path
is nil, so lines 62 and 63 here will always raise if wkhtml_path
or chrome_path
is nil.
As an experiment, I resolved the error locally by switching line 63 to the following to coerce any nil
s to an empty string:
chrome_exists = File.exists?(options[:chrome_path] || "")
That way File.exists?
will return false for nil paths, and raise_or_continue
can do its thing and raise or not depending on configuration.
If this seems like a reasonable way to get around the File.exists?
nil problem, I can open a PR.
Thanks!
Hi,
I'm look for documentation or sample on how to use it with phoenix. Sorry if it's a dummy question, but I'm new to elixir and phoenix. But I need to do some thing like this ruby code.
def print
respond_to do |format|
format.html do
render file: "/pipedrive/#{@template}.html.erb"
end
format.pdf do
render :pdf => "#{@proposal["title"]} - #{@proposal["organization"]["name"]}",
:template => "/pipedrive/#{@template}.html.erb"
end
end
end
So I need to give the name and render the choose template with all variables in PDF.
I'm new to elixir so apologies if this is on my end.
This is on macOS Sierra with Elixir 1.9.1
Erlang/OTP 22 [erts-10.4.4] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [hipe] [dtrace]
Elixir 1.9.1 (compiled with Erlang/OTP 22
I'm following this example and it works if I remove the options on the PdfGenerator.generate command. With the options I get the following error
(My Module is named GlsPdf)
iex(4)> GlsPdf.generate_pdf(["Bananas", "Apples", "Yogurt", "Beans", "Potatos"])
11:26:55.019 [debug] {"/usr/local/bin/wkhtmltopdf", ["--dpi", "300", "--page-size", :letter, "/var/folders/z8/247_d97d7y76f3_prnn_q4q80000gp/T/8UQrRJeq.html", "/var/folders/z8/247_d97d7y76f3_prnn_q4q80000gp/T/8UQrRJeq.pdf"]}
** (ArgumentError) all arguments for System.cmd/3 must be binaries
(elixir) lib/system.ex:782: System.cmd/3
(pdf_generator) lib/pdf_generator.ex:141: PdfGenerator.generate/2
(gls_pdf) lib/gls_pdf.ex:26: GlsPdf.generate_pdf/1
If I remove the arguments to PdfGenerator.generate it works fine.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.