0

Here is the requirement:

In my web-app developed in Ruby on Rails, we require to have an option to upload a PDF form template to the system, take it back in the browser itself and the user should be able to fill up the PDF form online and finally save it back to the server.

Then, user will come and download the updated PDF form from the application. I've searched a lot but couldn't find a proper solution to it. Please suggest.

Rajesh Omanakuttan
  • 6,788
  • 7
  • 47
  • 85

1 Answers1

1

As I stated for prebuilt PDF's with form fields already embedded I use pdtk Available Here and the active_pdftk gem Available Here. This is the standard process I use but yours may differ:

 class Form
   def populate(obj)
    #Stream the PDF form into a TempFile in the tmp directory
    template = stream
    #turn the streamed file into a pdftk Form
    #pdftk_path should be the path to the executable for pdftk
    populated_form =  ActivePdftk::Form.new(template,path: pdftk_path)
    #This will generate the form_data Hash based on the fields in the form
    #each form field is specified as a method with or without arguments
    #fields with arguments are specified as method_name*args for splitting purposes
    form_data = populated_form.fields.each_with_object({}) do |field,obj|
      meth,args = field.name.split("*")
      #set the Hash key to the value of the method with or without args
      obj[field.name] = args ? obj.send(meth,args) : obj.send(meth)
    end     
    fill(template,form_data)
  end
  private 
  def fdf(waiver_data,path)
    @fdf ||= ActivePdftk::Fdf.new(waiver_data)
    @fdf.save_to path
  end
  def fill(template,waiver_data)
    rand_path = generate_tmp_file('.fdf')
    initialize_pdftk.fill_form(template,
                               fdf(waiver_data,rand_path),
                               output:"#{rand_path.gsub(/fdf/,'pdf')}",
                               options:{flatten:true})
  end
  def initialize_pdftk
    @pdftk ||= ActivePdftk::Wrapper.new(:path =>pdftk_path)
  end 
end

Basically what this does is it streams the form to a tempfile. Then it converts it to a ActivePdftk::Form. Then it reads all the fields and builds a Hash of field_name => value structure. From this it generates an fdf file and uses that to populate the actual PDF file and then outputs it to another tempfile flattened to remove the fields from the final result.

Your use case might differ but hopefully this example will be useful in helping you achieve your goal. I have not included every method used as I am assuming you know how to do things like read a file. Also my forms require a bit more dynamics like methods with arguments. Obviously if you are just filling in raw fixed data this portion could be changed a bit too.

An example of usage given your class is called Form and you have some other object to fill the form with.

 class SomeController < ApplicationController
   def download_form
     @form = Form.find(params[:form_id])
     @object = MyObject.find(params[:my_object_id]) 
     send_file(@form.populate(@object), type: :pdf, layout:false, disposition: 'attachment')
   end
 end

This example will take @form and populate it from @object then present it to the end user as a filled and flattened PDF. If you just needed to save it back into the database I am sure you can figure this out using an uploader of some kind.

engineersmnky
  • 25,495
  • 2
  • 36
  • 52