Rails 3 and PDFKit. How to specify page size? - ruby-on-rails

I have been looking in the documentation but can't find the answer. How can I specify the page size of my pdf document and what are the available page sizes? I keep on looking and looking but I can't find good documentation. Please point me to a URL or let me know how can I code some page size into my PDF document.
Oh and I don't want to do that on any config file because I need to generate PDf documents of different sizes.
NOT in config file...
PDFKit.configure do |config|
config.wkhtmltopdf = `which wkhtmltopdf`.to_s.strip
config.default_options = {
:encoding=>"UTF-8",
:page_size=>"A4", #or "Letter" or whatever needed
:margin_top=>"0.25in",
:margin_right=>"1in",
:margin_bottom=>"0.25in",
:margin_left=>"1in",
:disable_smart_shrinking=>false
}
end

You can set the page size when creating a new PDF like this:
kit = PDFKit.new(source, :page_size => "Legal")
PDFKit uses WKHTMLTOPDF which in turn uses QPrinter. You can find the available sizes in the QPrinter documentation (there's a bunch), but its pretty safe to say that any size paper you want is available. Also, you can set a custom size if you can't find what you need.
NB: If you don't set a default option for page_size in a config somewhere AND don't supply one in your method call, PDFKit will use its internal default (Letter). See line 10 of lib/pdfkit/configuration.rb

Pdkit accepts custom sizes:
PDFKit.configure do |config|
config.wkhtmltopdf = `which wkhtmltopdf`.strip
config.default_options = {
:page_width => '1682',
:page_height => '2378'
}
end
The sizes must be in milimeters (wkthmltopdf documentation).

Since it's using wkhtmltopdf to generate the PDFs I'm assuming you can use the same options that it supports. In a wkhtmltopdf manual I found, it mentions the following site for a list of sizes:
http://doc.trolltech.com/4.6/qprinter.html#PaperSize-enum
To set the page size, you can use the :page_size option like so:
PDFKit.new(html, :page_size => 'Letter')

Related

How can I merge all PDF in one file with wickedpdf?

The way I'm working right now is I'm generating multiple pdf files and sending them all one at a time for the user to download, but the problem is sometimes they end up with too many files.
How can I merge all pdfs in a single file before sending them to the user?
I use combine_pdf gem.
To combine PDF files:
pdf = CombinePDF.new
pdf << CombinePDF.load("file1.pdf") # one way to combine, very fast.
pdf << CombinePDF.load("file2.pdf")
pdf.save "combined.pdf"
You can also parse PDF files from memory. Loading from the memory is
especially effective for importing PDF data recieved through the
internet or from a different authoring library such as Prawn:
pdf_data = prawn_pdf_document.render # Import PDF data from Prawn
pdf = CombinePDF.parse(pdf_data)
If you want to use some tool like PDFTk or CombinePDF, all you should need to do is prerender your individual PDFs by using something like:
pdf1 = render_to_string(pdf: 'pdf1', template: 'pdf1')
pdf2 = render_to_string(pdf: 'pdf2', template: 'pdf2')
or
pdf1 = WickedPdf.new.pdf_from_string(some_html_string)
pdf2 = WickedPdf.new.pdf_from_string(another_html_string)
If those tools won't take a PDF as a string, you may need to write them to tempfiles first.
If you don't want to introduce another dependency to merge things, wkhtmltopdf can take multiple pdf files (or urls), and render them all as one pdf with a command similar to this:
wkhtmltopdf tmp/tempfile1.html tmp/tempfile2.html tmp/output.pdf
Knowing this, you could prerender your templates, with layouts and everything, out to HTML strings, then pass them into wkhtmltopdf something like this:
# app/models/concerns/multipage_pdf_renderer.rb
require 'open3'
class MultipagePdfRenderer
def self.combine(documents)
outfile = WickedPdfTempfile.new('multipage_pdf_renderer.pdf')
tempfiles = documents.each_with_index.map do |doc, index|
file = WickedPdfTempfile.new("multipage_pdf_doc_#{index}.html")
file.binmode
file.write(doc)
file.rewind
file
end
filepaths = tempfiles.map{ |tf| tf.path.to_s }
binary = WickedPdf.new.send(:find_wkhtmltopdf_binary_path)
command = [binary, '-q']
filepaths.each { |fp| command << fp }
command << outfile.path.to_s
err = Open3.popen3(*command) do |stdin, stdout, stderr|
stderr.read
end
raise "Problem generating multipage pdf: #{err}" if err.present?
return outfile.read
ensure
tempfiles.each(&:close!)
end
end
And call in your controller something like this:
def fancy_report
respond_to do |format|
format.pdf do
doc1 = render_to_string(template: 'pages/_page1')
doc2 = render_to_string(template: 'pages/_page2')
pdf_file = MultipagePdfRenderer.combine([doc1, doc2])
send_data pdf_file, type: 'application/pdf', disposition: 'inline'
end
end
end
However, this only covers the simplest of cases, you'll have to do the work of rendering the headers and footers if you need them, parsing (or adding) any options you might need.
This solution originally came from https://github.com/mileszs/wicked_pdf/issues/339 so it may be helpful to look there for more details on this strategy.
Try PDFtk. In my opinon, it is the best library for editing PDF files, and there are some gems that wraps it for access from Ruby.

PDFKit header or footer not working

I am trying to add page numbers to each page of pdf generated using PdfKit. The following is my code :
content = File.read( "report.html.erb")
template = ERB.new(content)
set_margin = 0.to_s
kit = PDFKit.new(template.result(binding), :header_center => "Page [page] of [toPage]", page_width: '157.42', page_height: '52.77', :margin_top => set_margin+'in', :margin_right => set_margin+'in', :margin_bottom => set_margin+'in', :margin_left => set_margin+'in')
kit.to_file(file_path)
No header is getting displayed on the generated pdf. Please provide a solution for this.
Please type wkhtmltopdf --help in console. I believe, you have not patched Qt library with wkhtmltopdf fixes, hence you will see at the bottom of output:
Reduced Functionality:
This version of wkhtmltopdf has been compiled against a version of QT without
the wkhtmltopdf patches. Therefore some features are missing, if you need
these features please use the static version.
Currently the list of features only supported with patch QT includes:
Printing more then one HTML document into a PDF file.
Running without an X11 server.
Adding a document outline to the PDF file.
Adding headers and footers to the PDF file.
Generating a table of contents.
Adding links in the generated PDF file.
Printing using the screen media-type.
Disabling the smart shrink feature of webkit.
To print out headers and footers one should rebuild Qt library with patches provided by wkhtmltopdf.

Prawn: how to set document's printable dimensions

I'm generating a pdf with prawn. Basically, I generate the document and I fill it with some images.
The problem comes when I download the file and I try to print it. The dimensions are not set to the ones I previously specified.
pdf = Prawn::Document.new(page_size: "A3", margin: PAGE_MARGIN, page_layout: :landscape)
When I try to print it, the default page size is "A4" instead of "A3"
How can I solve this?
I tried to attach some metadata but it didn't work correctly.
Thanks in advance!
In the case where you're generating the document within its own class, this also works to declare the paper size:
class EnvelopePdf < Prawn::Document
def initialize(_item_array, _type_of_item)
super(:page_size => [324, 684], :page_layout => :landscape) # 4.5" by 9.5", which is No 10 envelopes
... application-specific initialization code here ...
print_the_envelopes
end
Using prawn 1.3.0:
require "prawn"
pdf = Prawn::Document.new(:page_size => 'A3')
pdf.text "Hello World!"
pdf.render_file("export.pdf")
in terminal:
pdfinfo export.pdf
outputs:
Creator: Prawn
Producer: Prawn
Tagged: no
Form: none
Pages: 1
Encrypted: no
Page size: 841.89 x 1190.55 pts
Page rot: 0
File size: 842 bytes
Optimized: no
PDF version: 1.3

Edit existing pdf file metadata with ruby (Apply Password protection)

I am uploading a pdf file using paperclip to s3. I want to apply password protection on the fly to the uploaded pdf file.
I tried to use the code given in question How to edit or write on existing PDF with Ruby?! to edit existing pdf file (the tmp file used by the paperclip) and try to apply password protection using
Prawn::Document.generate("tmp/abc.pdf",:template => params[:ebook].path) do encrypt_document(:user_password => 'foo', :owner_password => 'bar',
:permissions => { :print_document => false,
:modify_contents => false,
:copy_contents => false,
:modify_annotations => false } end
Is the template support still exist in prawn or it had been deprecated as i didn't find anything regarding template in the prawn manual! ?
Is there any other way or any other gem to do so ?
Thanks.
template was removed in version 0.13.0 because it was too buggy :
Support for templates was dropped in Prawn 0.13.0, disabled by default in 0.14.0, and extracted in 0.15.0.
This gem includes the extracted templates code, which is completely unsupported, but provides the old functionality that was in Prawn 0.12.0 for years.
source : https://github.com/prawnpdf/prawn-templates
As he said, you can try to add the library to your current Prawn installation.
Otherwise you can use pdftk with Open3 module (http://www.pdflabs.com/tools/pdftk-the-pdf-toolkit/) :
require 'open3'
file_name = 'hello_world_1.pdf' # input
file_name_output = 'hello_world_2.pdf' # output
usr = 'foo'
pwd = 'bar'
pdftek = './pdftk.exe' # tested on windows
Open3.popen3("#{pdftek} #{file_name} output #{file_name_output} owner_pw #{pwd} user_pw #{usr}") do |stdin,stdout,stderr|
# ...
end
There is also a wrapper for ruby but I haven't test it yet : https://github.com/tcocca/active_pdftk

How to improve dpi/resolution pdfkit

Currently using pdfkit, for the most part it's been great to use.
The only issue is line thickness. Borders on the source html look great, on the pdf generated look much thicker.
Also thickness varies in the document. On lines of the same width, it appears thicker in places. Even borders on the same div may appear thicker on the 3 of the 4 borders, even though they have the same CSS.
Any way to remedy this?
Well if you explore the extended help -H on wkhtmltopdf you would find a options called dpi
So perhaps you can set a dpi in pdfkit something like this
PDFKit.configure do |config|
config.wkhtmltopdf = '/path/to/wkhtmltopdf'
config.default_options = {
:page_size => 'Legal',
:print_media_type => true,
:dpi => [your dpi setting]
}
# Use only if your external hostname is unavailable on the server.
config.root_url = "http://localhost"
end
Note
Having said that it you examine the help deeply you would know that that it states
-d, --dpi <dpi> Change the dpi explicitly (this has no
effect on X11 based systems)
I clearly state it has no effect on system that based on X11 so I would rather see that of any help for you
Other options
So dpi options is hardly of use what are other options ?
Well in fact there is one check this link and trace to last comment and see some of that help in your quest (i.e try increasing the resolution of the xvfb in case if your running an xvfb server)
Hope this help

Resources