#220
Jun 28, 2010

PDFKit

Generating PDFs in plain Ruby can be a lot of work. Instead, consider generating PDFs from HTML using PDFKit.
Tags: plugins views
Download (18.5 MB, 8:14)
alternative download for iPod & Apple TV (16.8 MB, 8:14)

Resources

bundle install
rake middleware
# config/application.rb
config.middleware.use "PDFKit::Middleware", :print_media_type => true
<!-- layouts/application.html.erb -->
<%= stylesheet_link_tag 'application', :media => "all" %>

<!-- orders/show.html.erb -->
<p id="pdf_link"><%= link_to "Download Invoice (PDF)", order_path(@order, :format => "pdf") %></p>
/* application.css */
@media print {
  body {
    background-color: #FFF;
  }

  #container {
    width: auto;
    margin: 0;
    padding: 0;
    border: none;
  }
  
  #line_items {
    page-break-before: always;
  }
  
  #pdf_link {
    display: none;
  }
}

RSS Feed for Episode Comments 27 comments

1. Zolzaya Jun 28, 2010 at 01:24

Thanks very much for the episodes and best wishse.


2. nacho Jun 28, 2010 at 01:48

and what about epub?
any gem preferences?

thanks for your excellent work.


3. Sevos Jun 28, 2010 at 01:57

Thanks! You saved my life!


4. Andrea Jun 28, 2010 at 02:05

Ryan, great job as usual. I was already planning to check out those gems during these days so the timing of this screencast is just perfect.


5. Justin Halsall Jun 28, 2010 at 02:28

Awesome with a capital A, I have been waiting for a library like this for ages.


6. Jermaine Oosterling Jun 28, 2010 at 03:34

Ryan,

Great stuff. The episode came sooner than I expected.

Thanks.

- Jermaine


7. Dave Jun 28, 2010 at 04:09

A great gem! I love that it can be used as middleware! Thanks so much for the screencasts!


8. Deb Jun 28, 2010 at 05:32

This is fantastic. Prawn drives me nuts.


9. badboy_ Jun 28, 2010 at 06:30

hm, pdfkit seems quite nice. But in a simple test umlauts weren't displayed correctly with wkhtmltopdf =/
I don't have the time to figure this out for now.


10. Saxon Jun 28, 2010 at 09:02

How possible is it to have Rails automatically save a copy of this pdf on the server? I need a confirmation sheet for our folks in the office to use and I'd prefer to not have to do them one at a time if possible.


11. Saxon Jun 28, 2010 at 09:07

Though, perhaps the better way to look at this is to render one massive pdf of the index template with some special formatting and page breaks instead of 500 show template pdfs.


12. Ross Jun 28, 2010 at 13:28

Curious to know if anybody has tried creating a table including images?


13. Bijan Jun 29, 2010 at 01:11

really really cool screencast and very nice thing this pdfkit :)
Prawn for clean structures
PDFKit for fancy looks ;)


14. Pedro Teixeira Jun 29, 2010 at 04:09

Great screencast, once again you were providential:
Just when I was thinking I had to learn Prawn I opened my RSS reader and there was your fresh new tutorial!
Thanks!


15. JonnieCache Jun 29, 2010 at 06:28

"Curious to know if anybody has tried creating a table including images?"

it should work for *any* html, as it uses webkit (the renderer from chrome, safari etc.) to 'display' the html page internally, then draws this into a pdf, in the same way you can export a pdf directly from any program on os x by clicking the PDF button in the print dialog.

"How possible is it to have Rails automatically save a copy of this pdf on the server? I need a confirmation sheet for our folks in the office to use and I'd prefer to not have to do them one at a time if possible."

you could probably create a controller action which uses pdfkit or similar to save a pdf directly to an arbitrary filesystem path. look through its api for a method which returns a File or IO object, it likely uses one internally anyway.


16. JonnieCache Jun 29, 2010 at 06:39

actually if you only need to do it once/rarely a rake task would be better than mucking up your controllers and routing


17. Pedro Teixeira Jun 29, 2010 at 09:05

Hi again Ryan,

Can't really make page-break-before work, it's always cutting my tables...
What version of wkhtmltopdf are you using?


18. mileszs Jun 29, 2010 at 11:43

Thanks for plug, Mr. Bates!

I will very soon be working on wicked_pdf with the intention of bringing it up to date on Rails 3, and Ruby 1.9.2. I might be looking at relying upon PDFKit, if I can do so without losing any of the flexibility of wicked_pdf. I think that will ultimately be better for both projects.


19. Pedro Teixeira Jun 29, 2010 at 14:44

Found out that page-break-before only works if you have a really simple layout, with very few nestings.
Now I only wish "page-break-inside: avoid;" would work...


20. Rupert Fisher Jun 30, 2010 at 01:27

Got to love PDFs and this should be very powerful. Can't wait to deploy in my app. Just one thing though, sems very straightforward, I followed the steps, in a test 2.3.8 app with a simple scaffold.

Can't get any text to display on the PDF itself, a PDF renders from the show action /show/1.pdf : but it just contains the word "nil" rather than displaying the record as the html view does.

Sorry if I'm being dense, any ideas?


21. Jan Jun 30, 2010 at 02:49

page-break-avoid does not yet work in wkhtmltopdf. it's because this would require heavy changes in webkits rendering ...

If page-breake-before does not work. Try doing "clear: both; page-break-before: always; display: block;" ...

The clearing should do the trick.


22. Fredrik Jun 30, 2010 at 02:59

Anyone knows how to display the current page number and the total number of pages?


23. Pierre Jun 30, 2010 at 06:48

Same problem as Rupert Fisher... I obtain a 'nil' blank page every time :(


24. marek Jun 30, 2010 at 06:49

Thank you for a great cast.

pdfKiT works great for me but only on Rails 3
in Rails 2.3.8 if I do ".pdf" on url it returns empty pdf with "nil". Anybody had that problem ?
Creating from command line works without any problems.

Many thanks.


25. Juergen Jun 30, 2010 at 13:45

Works fine in irb console but in the real app I get the following error:

Processing PostsController#show to pdf (for 127.0.0.1 at 2010-06-30 22:44:01) [GET]
  Parameters: {"id"=>"1"}
  Post Load (0.4ms) SELECT * FROM "posts" WHERE ("posts"."id" = 1)
Completed in 13ms (View: 4, DB: 0) | 406 Not Acceptable [http://localhost/posts/1.pdf]

Anybody know who to get this to work?

Any help would be greatly appreciated J.


26. RurouniJones Jun 30, 2010 at 20:51

Good lord man, you need to do something about the spam problem.

Route all comments through Kismet or Defensio for a start?


27. mikedc55 Jul 01, 2010 at 16:41

Thanks for this. Awesome alternatives to the expensive princeXML.


28. Juanma Jul 02, 2010 at 01:13

I am having the same error that marek(comment 26).

Environment:
Rails 2.3.8 con bundle.
wkhtmltopdf in '/usr/local/bin'

And the error:
406 Not Acceptable [http://localhost/whatever.pdf] and no output.

Any ideas?
Thank you


29. AlexMC Jul 02, 2010 at 09:33

Hi, Great screencast.

having the same problem that 26 and 66

Can anyone give a hand?


30. marek Jul 06, 2010 at 01:25

To solve the problem with Rails 2.3++ look at http://github.com/perenecabuto/PDFKit/commit/c61f8d683c2894c2cfecf08b43707c63514c4c9f it works for me.


31. Michelangelo Altamore Jul 06, 2010 at 04:17

Hello Ryan,
thank you for another great episode. You can actually obtain the url text using css:

http://gist.github.com/465259

Of course, it's better to put that into a print.css stylesheet. I am not sure if it works in IE6, BTW.


32. Amit Patel Jul 06, 2010 at 12:32

Hi Ryan,

I was desperately looking for a working example of PDFKIT.

This is great!!!!

Thanks a lot!!!!!


33. Kurt Werle Jul 06, 2010 at 14:25

Great episode; I'll have to check pdfkit out.

One note: instead of #pdf_link, maybe you could have used .no_print. It seems likely that there will be other items you don't want to print - using an id tag for that one seems pretty heavy.

But that's a nit! Thank again.


34. Hosein Shafiei Jul 08, 2010 at 05:53

Thank god for the creation of ryanb ! ;) you save my ass every time, bro.


35. Dirk Jul 13, 2010 at 20:56

For everyone getting only "nil" rendered, check your logs. Likely it will say it want's a genereic template such as show.erb.
The patch quoted above which is at http://github.com/perenecabuto/PDFKit/commit/c61f8d683c2894c2cfecf08b43707c63514c4c9f
might work but it's not yet in the master branch AFAICT.


36. JManGt Jul 14, 2010 at 22:04

Has anyone been able to solve the 406 error on Rails 2.3.8 ?


37. cash 4 gold Jul 18, 2010 at 18:31

Great post, I like it :))


38. dfafdas Jul 18, 2010 at 21:03

hello


39. John Jul 19, 2010 at 04:57

Hi Fredrik,

to add page numbers, you can add some spans to the header HTML that will be replaced, see: http://madalgo.au.dk/~jakobt/wkhtmltopdf-0.10.0_beta4-doc.html#Headers%20And%20Footer%20Options. Setting the header is easier using wicked_pdf.


40. Christian Audigier Jul 20, 2010 at 02:51

The article written by you very good, I like it very much. I will keep your new article.


41. personal wealth academy Jul 20, 2010 at 08:32

Great Buddy how you know about this in very details, it is really very interesting and knowledgeable things.


42. elvankent halı yıkama Jul 22, 2010 at 00:14

Very pleased to be here!


43. stoic Jul 22, 2010 at 13:49

I've been using Prawn, but find it too time consuming. I installed PDFKIT and can run my page if I type in the URL.pdf, but when using the link_to... :format => pdf, it still launches the Prawn formatted doc.

I've removed the pdf.prawn doc, the environment.rb requirement, as well as the vendor/plugin contents, but it still launches the prawn doc. WTF?

I tried uninstalling the Prawn gem, but phusion won't start my app at all.

So...where else are these prawn files hiding that won't let PDFKIT take over?


44. cheap air jordans Jul 25, 2010 at 08:39

I've been using Prawn, but find it too time consuming. I installed PDFKIT and can run my page if I type in the URL.pdf, but when using the link_to... :format => pdf, it still launches the Prawn formatted doc.


45. DVD to iPad Converter Jul 25, 2010 at 19:22

I don’t know what to say except that I have enjoyed dsd


48. bingobob Jul 27, 2010 at 09:15

One thing I'd like to know - this is great but it bestows a PDF view on all the resources, could be good but overkill for what I'd like. How would I have more fine grain control over what gets the PDF treatment <- maybe with a link on certain pages saying "show pdf".


48. asics shose Jul 28, 2010 at 00:22

It is my pleasure to read this article,I look forward to reading more.


49. ASUS EEE PC 2G SURF (256 RAM) Battery Jul 30, 2010 at 23:15

Thanks so much for the screencasts!


49. asus M5000 Series battery Jul 30, 2010 at 23:16

The article written by you very good, I like it very much. I will keep your new article.It is my pleasure to read this article,I look forward to reading more.


50. wholesale jeans Jul 31, 2010 at 01:25

A great gem! I love that it can be used as middleware! Thanks so much for the screencasts!


51. Paulie Aug 01, 2010 at 08:22

@bingobob: I was also concerned that every page can be rendered as .pdf. I only have one page that makes sense. Instead of doing the middleware step, I think I can just call: `wkhtmltopdf --page-width 8.5in --page-height 11.0in http://my.domain.com/my/url output.pdf` from my controller in the one place it is needed.


52. pumps Aug 01, 2010 at 19:29

e that makes sense. Instead of doing the middleware step, I think I


53. replacement laptop battery Aug 02, 2010 at 02:25

Good site..I can learn more about code


54. canlimac izle Aug 05, 2010 at 11:28

reat article ...thanks admin


56. california surety bonds Aug 06, 2010 at 10:46

Can I just say, this blog is what got me through the day today. Every time I read it, I just get more and more excited about whats next. Very refreshing blog and very refreshing ideas. I'm glad that I came across this when I did. I love what you've got to say and the way you say it.


58. cheap coogi Aug 09, 2010 at 10:19

Here we have popular Polo T-shirt.


59. Ken Aug 09, 2010 at 11:37

If you don't want to use the middleware for rendering (this might be the case if you want add a custom filename to the send_data method), you can do something like this:

      format.pdf {
        html = render_to_string(:action => "show.html.erb")
        kit = PDFKit.new(html)
        kit.stylesheets << "#{Rails.root}/public/stylesheets/print.css"
        send_data kit.to_pdf, :filename => "Your-custom-filename.pdf", :type => 'application/pdf'
      }


60. UGG Boots on sale Aug 10, 2010 at 18:38

Gooooooooooooooooooood luck ~~!!


61. Mike Aug 12, 2010 at 21:48

How to cache the PDF using Rails page caching and PDFKit

1. Disable the PDFKit middleware so that your controller handles the generation of the PDF.

2. Register PDF as a mime-type in environment.rb:
Mime::Type.register "application/pdf", :pdf

3. In your controller, cache pages just like normal with caches_page :show

4. create a format.pdf call in your respond_to block and init a new PDFKit object, pass in the url to the current action and call to.pdf on it.

respond_to do |format|
      format.html # show.html.erb
      format.pdf { render :text => PDFKit.new( post_url(@post) ).to_pdf }
end

Now in your cache directory you'll create two cache files - one .html and one .pdf.


62. oppo Aug 15, 2010 at 08:38

This was really useful. Thanks Ryan!


63. coffee roaster Aug 16, 2010 at 18:20

Great job! Thanks for the useful informations. This is a bog help for us.


64. Rip Blu-ray for Mac Aug 18, 2010 at 01:27

Thanks,it's so good.
suport!


65. Wholesale hats Aug 20, 2010 at 19:58

That is an awfully astounding column you've posted.Thanks a lot for that a fantastically amazing post!


66. converse all star Aug 20, 2010 at 20:36

love converse all star,love yourself.Warm welcome.


67. converse all star Aug 20, 2010 at 20:53

love converse all star,love yourself.High quality low price.It's fit for you.


68. tile floor vacuum Aug 24, 2010 at 10:25

The blog article very surprised to me! Your writing is good. In this I learned a lot! Thank you!


69. PDF to Images Converter Aug 24, 2010 at 22:52

Some times, to a certain need, we have to convert PDF to image for enjoyment.


70. louis vuitton shoes Aug 26, 2010 at 21:17

Thanks for sharing your article. I really enjoyed it. I put a link to my site to here so other people can read it. My readers have about the same interets


71. mbt shoes sale Aug 28, 2010 at 09:50

 format.html # show.html.erb
      format.pdf { render :text => PDFKit.new( post_url(@post) ).to_pdf }
end

Now in your cache directory you'll create two cache files - one .html and one .pdf.


72. cheap mbt shoes Aug 28, 2010 at 10:10

we have to convert PDF to image for enjoyment.


73. cheap ugg boots sale Aug 28, 2010 at 10:19

Now in your cache directory you'll create two cache files - one .html and one .pdf.


74. rap Aug 29, 2010 at 08:46

Great post, I like it :))


75. herve leger dress Aug 30, 2010 at 20:09

Thanks for sharing your article. I really enjoyed it. I put a link to my site to here so other people can read it.


76. snow boots Aug 30, 2010 at 20:10

I was thinking I had to learn Prawn I opened my RSS reader and there was your fresh new tutorial!


77. jenifer Aug 31, 2010 at 23:47

Coucou ! Pas trop le temps de te lire mais merci aussi.


78. levis belts Sep 01, 2010 at 20:40

Came across your blog when I was searching bing I have found the bit of info that
I found to be quite useful.


79. blu ray ripper Sep 01, 2010 at 23:17

This is really a nice guide for Newbies like me. Thank you.

Add your comment:

(SKIP THIS ONE)

(required)

(not shown)


(use pastie or gist for code)

sponsored by:
if you want to help:
required:
Get Quicktime Player
Give Back to Open Source