How to edit or write on existing PDF with Ruby?
Asked Answered
L

8

43

I have a couple of PDF template files with complex content and several blank regions/areas in them. I need to be able to write text in those blank regions and save the resulting PDFs in a folder.

I googled for answers on this question quite intensively, but I didn't find definite answers. One of the better solutions is PDF::Toolkit, but it would require the purchase of Adobe Acrobat to add replaceable attributes to existing PDF documents.

The PHP world is blessed with FPDI that can be used to simply open a PDF file and write/draw on it over the existing content. There is a Ruby port of this library, but the last commit for it happened at the beginning of 2009. Also that project doesn't look like it is widely used and supported.

The question is: What is the better Ruby way of editing, writing or drawing on existing PDFs?

This question also doesn't seem to be answered on here. These questions are related, but not really the same:

Liber answered 7/2, 2012 at 23:58 Comment(0)
J
35

you have to definitely check out Prawn gem, by which you can generate any custom pdf files. You can actually use prawn to write in text into existing pdfs by treating the existing PDF as a template for your new Prawn document.

For example:

filename = "#{Prawn::DATADIR}/pdfs/multipage_template.pdf"
Prawn::Document.generate("full_template.pdf", :template => filename) do
  text "THis content is written on the first page of the template", :align => :center
end

This will write text onto the first page of the old pdf.

See more here: http://prawn.majesticseacreature.com/manual.pdf

Jessalin answered 9/2, 2012 at 5:47 Comment(5)
Yep, I've considered it (and even listed in my question), but editing existing PDFs is a requirement for my project. Thank you for the answer.Liber
I have this problem, any idea? #12076799Riparian
I use exactly this method to extensively add text to existing PDFs. Why doesn't this answer work for you?Diagnostic
Support for templates was dropped in Prawn 0.13.0, disabled by default in 0.14.0, and extracted in 0.15.0. - from github.com/prawnpdf/prawn-templatesCheckrein
After template support was deprecated in Prawn (as detailed in @MichaelReinsch's post), I ended up writing a Ruby implementation for combining PDF files, stamping them, merging them (in sequence as well as one on top of the other), adding simple text, extracting PDF fonts and other simple tasks. This gem had been mentioned in Paweł Gościcki's answer later on: combine_pdfLed
S
25

Since Prawn has removed the template feature (it was full of bugs) the easiest way I've found is the following:

  1. Use Prawn to generate a PDF with ONLY the dynamic parts you want to add.
  2. Use PDF::Toolkit (which wraps PDFtk) to combine the Prawn PDF with the original.

Rough Example:

require 'prawn'
require 'pdf/toolkit'

template_filename = 'some/dir/Awesome-Graphics.pdf'
prawn_filename = 'temp.pdf'
output_filename = 'output.pdf'

Prawn::Document.generate(prawn_filename) do
  # Generate whatever you want here.
  text_box "This is some new text!", :at => [100, 300]
end

PDF::Toolkit.pdftk(prawn_filename, "background", template_filename, "output", output_filename)
Surname answered 18/5, 2015 at 23:39 Comment(0)
C
23

I recommend prawn for generating PDFs and then using combine_pdf to combine two generated PDFs together into one. I use it like this and it works just fine.

Short example (from the README) of how to combine two PDFs:

company_logo = CombinePDF.load("company_logo.pdf").pages[0]
pdf = CombinePDF.load "content_file.pdf"
pdf.pages.each { |page| page << company_logo } # notice the << operator is on a page and not a PDF object.
pdf.save "content_with_logo.pdf"
Cutcherry answered 1/6, 2015 at 9:58 Comment(2)
I found that this didn't work well for me, because the "logo" file (for me, it was an overall template, that I was just adding a little bit of text to) would cover up whatever I'd added (using Prawn::PDF, similar to some other answers). I found this to solve it for me, though (replacing what's inside the block on line 3 in this answer): page.replace(company_logo.copy << page)Jariah
This worked for me with what I think is a clearer solution than the PDF::Toolkit route which didn't work for me.Chipper
P
17

You don't need to use a combination of gems you can use just one gem!

Working with PDF's is really challenging in Ruby/Rails (so I have found out!)

This is the way I was able to add text dynamically to a PDF in rails.

add this gem to your gem file gem combine_pdf

and then you can use code like this:

# get the record from the database to add dynamically to the pdf
user = User.last

# get the existing pdf
pdf = CombinePDF.load "#{Rails.root}/public/pdf/existing_pdf.pdf"

# create a textbox and add it to the existing pdf on page 2
pdf.pages[1].textbox "#{user.first_name} #{user.last_name}", height: 20, width: 70, y: 596, x: 72

# output the new pdf which now contains your dynamic data
pdf.save "#{Rails.root}/public/pdf/output#{Time.now.to_s}.pdf"

You can find details of the textbox method here: https://www.rubydoc.info/gems/combine_pdf/0.2.5/CombinePDF/Page_Methods#textbox-instance_method

I spent days on this working through a number of different gems: prawn wicked_pdf pdfkit fillable_pdf

But this was by far the most smooth solution for me as of 2019.

I hope this saves someone a lot of time so they don't have to go through all the trial and error I had to with PDF's!!

Pocked answered 29/7, 2019 at 16:38 Comment(2)
wow :) I don't know why there is low upvote to this answer..this should be at the top.. you have given the complete working code and an elegant solution..Unerring
@CodeTree Thanks, glad it saved you all the pain I went through! Feel free to upvote so it can help more people!Pocked
R
1

The best I can think of is Rails-latex, it doesn't allow you to edit existing PDF files but it would allow you to set up template *.tex.erb which you may dynamically modify and compile them into PDF format (along with dvi and a number of others).

Rooster answered 9/2, 2012 at 5:32 Comment(1)
Thank you for this answer, but editing existing PDFs is a requirement in my case. For creating new PDFs something like prawn would've worked for me...Liber
B
1

PDFLib seems to do the thing you want and has ruby bindings.

Benavidez answered 9/2, 2012 at 7:2 Comment(4)
This indeed looks like a great tool, but since it is not open source (not free) - we'll have to consider the price. The version we can use is about $2100 - this is a lot of our low budget small project. Also this probably could not be considered a "Rails-way", since it is so expensive :) I'll probably go ahead with PDF::Toolkit and use it to populate PDF attributes values, instead of drawing on PDF. But thank you for this answer - I really appreciate it!Liber
Yeah, it's always hard to bite off a cost that big in the beginning. Purchased Prince XML for making PDFs a while back, and it seemed like a lot of money at the time, but it has paid off.Benavidez
I use Prince XML for one of my other projects too - it works, but not for this case I'm trying to tackle unfortunately.Liber
It's worth noticing that version "n-1" - v7 - is provided for free, with source code pdflib.com/en/download/free-software/pdflib-lite-7 - through, it is not supported. I also don't know how much "lite" is cut down on features.Smalley
N
0

According to my research, Prawn is one of the free and best gems I found. The template functionality isn't working in later version. The latest version I could find to work with templates is 1.0.0.rc2 - March 1, 2013. Couldn't find any later version which works with templates. So be mindful if you are using later versions than this. Check below thread for more info.

https://groups.google.com/forum/#!searchin/prawn-ruby/prawn$20templates/prawn-ruby/RYGPImNcR0I/7mxtnrEDHeQJ

PDFtk is another capable tool for PDF manipulation and to work with templates. But it mentions following points,

  • This library is free for personal use, but requires a license if used in production
  • This is a non-ruby command line tool

For more information please refer the below link http://adamalbrecht.com/2014/01/31/pre-filling-pdf-form-templates-in-ruby-on-rails-with-pdftk/

Neomineomycin answered 12/10, 2015 at 5:17 Comment(0)
S
0

You can use Origami gem to add a password to the existing pdf or edit it.

pdf = WickedPdf.new.pdf_from_url(pdf_params[:url])
temp_file = Tempfile.new('temp', encoding: 'ascii-8bit')
temp_file.write(pdf)

# Creates an encrypted document with AES256 and passwords.
pdf = PDF.read(temp_file.path).encrypt(cipher: 'aes', key_size: 256,user_passwd: pdf_params[:user_password], owner_passwd: pdf_params[:owner_password])
save_path = "#{File.basename(__FILE__, ".rb")}.pdf"

pdf.save(save_path)
temp_file.close
Syndicalism answered 23/3, 2021 at 7:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.