WKHTMLTOPDF with pdfkit on Rails ignoring table page breaks

匿名 (未验证) 提交于 2019-12-03 02:29:01

问题:

I know there are a lot of issues with wkhtmltopdf and page breaks that date back years, but I haven't worked out a solution yet. I'm using the PDFKit gem to generate my html pages into pdfs, but I don't want the pages to break in the middle of a table row.

I'm using wkhtmltopdf-binary (0.9.9.3), which looks to be the most updated version

My CSS:

@media print {    #scores table tr td, #scores table tr th {     page-break-inside: avoid !important;   }    table, tr, td, th, tbody, thead, tfoot {     page-break-inside: avoid !important;   }  } 

My table:

<div class="score_table">     <table id="scores" class="print-friendly">       <tbody>             <% @chapters.each do |chapter| %>                 <tr>                     <th colspan="3" ><%= chapter.name %></th>                 </tr>                    <% chapter.rules.each do |rule| %>                     <tr>                         <th colspan="2" >Rule: <%= rule.name %></th>                         <th></th>                     </tr>          <!-- Triggers -->                                    <% rule.triggers.each do |trigger| %>                         <tr>                             <td>T</td>                             <td><%= markdown(trigger.body) %></td>                             <td><%= markdown(trigger.explanation) %></td>                         </tr>                         <% if trigger.image? || trigger.image2? %>                             <tr>                                     <td></td>                                 <% if trigger.image? %>                                     <td><%= image_tag trigger.image.url(:thumb) %></td>                                 <% else %>                                     <td></td>                                 <% end %>                                    <% if trigger.image2? %>                                     <td><%= image_tag trigger.image2.url(:thumb) %></td>                             <% else %>                                 <td></td>                                <% end %>                                </tr>                            <% end %>                        <% end %>        <!-- Questions -->                       <% rule.questions.each do |question| %>                         <tr>                             <td>Q</td>                             <td><%= markdown(question.body) %></td>                             <td><%= markdown(question.answer) %></td>                         </tr>                         <% if question.image? || question.image2? %>                             <tr>                                     <td></td>                                 <% if question.image? %>                                     <td><%= image_tag question.image.url(:thumb) %></td>                                 <% else %>                                     <td></td>                                 <% end %>                                 <% if question.image2? %>                                        <td><%= image_tag question.image2.url(:thumb) %></td>                             <% else %>                                 <td></td>                             <% end %>                                    </tr>                            <% end %>                        <% end %>        <!-- Hints -->                       <% rule.hints.each do |hint| %>                         <tr>                             <td>H</td>                             <td><%= markdown(hint.body) %></td>                             <td><%= markdown(hint.explanation) %></td>                         </tr>                         <% if hint.image? || hint.image2? %>                             <tr>                                     <td></td>                                 <% if hint.image? %>                                     <td><%= image_tag hint.image.url(:thumb) %></td>                                 <% else %>                                       <td></td>                                 <% end %>                                    <% if hint.image2? %>                                 <td><%= image_tag hint.image2.url(:thumb) %></td>                             <% else %>                                   <td></td>                             <% end %>                                </tr>                            <% end %>                        <% end %>                    <% end %>             <% end %>     </tbody>     </table> </div> 

Is there a work around, or is there something that I'm doing wrong? This is the result:

I could post the PDFKit code as well, but it sounds like a wkhtmltopdf issue

***Update - My CSS @print isn't affecting the page when .pdf is added to the url. I have my stylesheet link with media: "all"

<%= stylesheet_link_tag    "application", media: "all", "data-turbolinks-track" => true %> 

Here's my initializer pdfkit.rb:

ActionController::Base.asset_host = Proc.new { |source, request|    if request.env["REQUEST_PATH"].include? ".pdf"     "file://#{Rails.root.join('public')}"   else     "#{request.protocol}#{request.host_with_port}"   end } 

If I can fix the CSS, then I probably will solve the page break issue!

回答1:

i added this in css it worked for me

@media print { #scores {       page-break-before: always;     } } 



回答2:

I am using version wkhtmltopdf 0.12.0

For me, page breaks ONLY work with --print-media-type. Without it, page break protection for images works, but not page-break-after or before.

I had to make a special css file for print media to get it work.

Setting the paper size to 'A3' or using the 'overflow: visible' didn't make any difference.

I ended up with the following:

in config/initializers:

PDFKit.configure do |config|   config.wkhtmltopdf = '/usr/bin/wkhtmltopdf'   config.default_options = {     :encoding=>"UTF-8",     :page_size => 'A3',     :zoom => 0.9,     :javascript_delay => 2000,     :print_media_type => true,     :footer_right => 'report, page [page] of [toPage]',     :no_background => true,   } end 

I am not 100% sure if the no_background is needed.

Then, in the controller:

def report_as_pdf     require 'nokogiri'     root_url = Rails.env.development? ? 'http://localhost:3000' : 'https://my.example.com'     html = render_to_string(layout: true, template: "reports/report_as_pdf").gsub('/assets', root_url + '/assets') # since wkhtmltopdf can not find the css files, we add the root_url to all assets     html_doc = Nokogiri::HTML(html)     html_doc.css('div.contain-to-grid').remove     html_doc.css('nav#rapportage_bar').remove     # Had to remove certain elements on the page. Not relevant for this particular problem, but it may help.     html = html_doc.to_html     filename = 'report_' + Time.now.to_s(:db)[0..9]     if Rails.env.development?       File.write("/tmp/#{filename}.html", html)       render :text => "wrote /tmp/#{filename}.html"       fork do         system("wkhtmltopdf --footer-right 'report, page [page] of [toPage]' --page-size 'A3' --zoom 0.9 --javascript-delay 2000 --no-background --print-media-type  file:////tmp/#{filename}.html  /tmp/#{filename}.pdf")       end       # forking was the only way I could get it to work in development mode, using thin as webserver instead of webrick (but it might work with webrick, I didn't try).     else       kit = PDFKit.new(html)       send_data(kit.to_pdf, :filename => filename + '.pdf', :type => 'application/pdf')       # all is simpeler in production mode.     end   end 

Note, that in the default layout (normally app/views/layouts/application.html.erb) I added one line to introduce a special css file for print:

stylesheet_link_tag    "application_print", media: "print" 

This file actually imports some tables from ZURB Foundation, which is cool.

@import "foundation/components/tables";  h1 {   font-variant: small-caps;   font-weight: bolder;   font-size: 320%;   border-bottom: 12px solid black;   margin-bottom: 20px;   margin-top: 80px;   }  h2 { (etc etc etc) 

To make page breaks in a view, I just insert this in the right places:

I hope this will be useful to someone someday.



回答3:

Can you upload the controller code where you've called PDFkit.new ?

Your stylesheet might not be included. Try adding the stylesheet in your controller code like this:

def export     kit = PDFKit.new(render_to_string(layout: false, handlers: [:haml], formats: :html, template: 'score_tables/export'))     kit.stylesheets << "#{Rails.root}/vendor/assets/stylesheets/bootstrap.css"     kit.stylesheets << "#{Rails.root}/app/assets/stylesheets/score_tables.css"     kit end 


回答4:

Here is how I fixed my issue. - Updated PDFKIT to as of ( 01/22/2014 ) - I had to move my table out of the <div> as the nested table messes everything up.

Example:

No div tag wrapping the table.

From

<div class="score_table"> <table id="scores" class="print-friendly"> ...rest of the HTML 

To

<table id="scores" class="print-friendly"> ...rest of the HTML 

Hope this helps.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!