4 Comments

Merging Pdf’s in Rails application


Alright, I had a lot of fun today trying to figure out how to merge pdf’s in our Rails application.

We are using pdfkit to create our pdf’s.  What I needed to do was to take several pdf’s and merge them into one large pdf.  Frankly I did not think it was even possible.  I found several Ruby gems that were supposed to do the job but everyone I tried was just another PITA dead end.

After getting pointed in the right direction by @m3talsmith, I ended up solving my issue the old school way.  So, if you have done this before with Ruby gems stick with it.  If not, here we go…

def merge_pdfs
   pdfs = []
   pdfs << @bulletin.pdf.path
   @bulletin.bulletin_inserts.first.bulletin_insert_items.each do |bii|
     if bii.pdf.present?
      pdfs << bii.pdf.path
     end
   end
   if pdfs.count > 1
     system "gs -dBATCH -dNOPAUSE -q -sDEVICE=pdfwrite -sOutputFile=temp.pdf #{pdfs.join(' ')}"
     system "cat '/Users/bob/Projects/bulletin-builder/temp.pdf' > #{@bulletin.pdf.path}"
   end
 end

I first started with an empty array for pdfs.  Then I went thru a couple of processes to add all the pdfs to the pdfs array.

After that, comes the old school.  Using Ghostscript (gs) we joined all of the pdfs and outputted them to a temp.pdf.  I tried several times unsuccessfully to overwrite the original pdf but I never got it to work correctly.  After creating the temp.pdf we used good old cat command to copy the temp.pdf to the original pdf.

If you know or find a better way, please tell me!!

4 comments on “Merging Pdf’s in Rails application

  1. Very helpful, thanks. Worked for me.

  2. Did you look at the combine_pdf gem ( https://github.com/boazsegev/combine_pdf )?

    It’s native Ruby and allows you to work with the PDF in the memory – so instead of expansive system calls, you can actually merge the PDF in the memory and send the response without any temporary files.

    after requiring the gem, you could add this to your code (instead of the system call):

    final = CombinePDF.new

    pdfs.each {|f| final << CombinePDF.load(f) }

    final.to_pdf # will return a PDF stream to be sent as a response or saved to a file.

    I wrote it after my search for a native Ruby solution left me disappointed.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: