Printing pdf in luminus

I am trying to do a simple print of a pdf in my luminus project. I am using the clj-pdf lib.

In my html page I have a simple button for the pdf:

 <form action="/pdf">
  <button class="button is-small is-link is-light">pdf</button>
  </form>

it calls my route page as follows:


(defn spdf [req]
  (pdf
  [{}
   [:list {:roman true}
          [:chunk {:style :bold} "a bold item"]
          "another item"
          "yet another item"]
   [:phrase "some text"]
   [:phrase "some more text"]
   [:paragraph "yet more text"]]
  "doc.pdf"))

(defn home-routes []
  [ "" 
   ;; {:middleware [middleware/wrap-csrf
   ;;               middleware/wrap-formats]}
   ["/pdf" spdf])

but all I get is an error message saying

# Error: 406

---

## 406 - Not acceptable

All I want is to print a pdf. any ideas?

I can’t comment well on the method you’re using but I found Print.js to be a convenient way to accomplish what you’re doing if your project involves CLJS. It was more seamless than I thought at a small scale.

(require '["print.js" :as printer])

Print.js can take DOM elements. To generate content on the fly, I created an element with visibility: hidden, just inlined in the HTML for convenience, and remounted its (invisible) contents on state change. For print.js you can override any existing CSS and style it with a custom stylesheet so visibility didn’t matter.

Once any content is mounted in the DOM e.g. reagent.dom/render, even if it’s not visually on the page,

(printer
 #js{:printable "output"
     :type "html"
     :css #js["/_css/reset.css" "/_css/printer.css"]
     :scanStyles false})
  • Print element with id output
  • Choose among options, html, image, pdf (pregenerated), or json
  • Pass a string or array with paths to external CSS

Alternatively, printer can take :style with a CSS string as opposed to :css with a filename, especially if you’re generating styles dynamically this could be useful to use in combination with garden or other CSS generators.

  • :scanStyles false ignores all existing CSS for the chosen element, i.e in my case visibility

One browser-based quirk was that no elements’ background colors would be set on the resulting PDF, whether an actual page background or an element like hr. This issue is resolved by adding

-webkit-print-color-adjust: exact !important;
color-adjust: exact !important;

to *, or any specific element where this is an issue.

Alternatively to creating HTML if that doesn’t work out in this context, you could generate a PDF any other way then pass the file directly to this small library

ok, I had some mixed experience with cljs, but I could try this.

But it would be interesting to see if my non clsj solution would be able to work.

Well, since working clojurescript here would just be for sake of using one javascript library I see how it wouldn’t be appropriate if you added all the overhead of that paradigm of the language for a simple use case,
Sorry don’t know the best solution for you with clj-pdf but I’ll be interested to see what solutions other people bring!

The ring default handler will return 406 Not Acceptable if you handler returns nil. Have you tried running the handler function on its own to make sure that it returns what you expect?

that is right. I did run the handler in the repl and it generated the pdf and returned nil. so now I have to figure out how to handle the nil return in my route function

Handlers have to return something to the browser so you probably want to return a “PDF printed successfully!” page of some sort.

I was thinking to return the pdf as a frame as follows:

(layout/render req "pdf.html" {)))

and in pdf.html:

<frame src="doc2.pdf"></frame>

but it is not working yet…

I am still struggling with displaying the pdf. I can generate the pdf and save it but not view it:
I would like to have something similar like:

File file:///prog/web/clojure/luminus/rental/doc2.pdf

but i doesn’t work like that.
this is one of the things that I tested:


(defn spdf [req]
  (let [fr (pdf
  [{}
   [:list {:roman true}
          [:chunk {:style :bold} "a bold item"]
          "another item"
          "yet another item"]
   [:phrase "some text"]
   [:phrase "some more text"]
   [:paragraph "yet more text"]]
  "doc2.pdf")]
    (selmer/render "doc2.pdf" {})))

but no success…