Skip to content

Instantly share code, notes, and snippets.

@micahroberson
Created July 13, 2013 00:35
Show Gist options
  • Star 29 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save micahroberson/5988843 to your computer and use it in GitHub Desktop.
Save micahroberson/5988843 to your computer and use it in GitHub Desktop.
Generate and save a pdf to S3 with wicked_pdf and paperclip
# Main reference was lascarides' post at http://stackoverflow.com/questions/14743447/getting-pdf-from-wickedpdf-for-attachment-via-carrierwave
# estimate.rb
# ...
has_attached_file :pdf,
storage: :s3,
s3_credentials: {
access_key_id: ENV['AWS_ACCESS_KEY_ID'],
secret_access_key: ENV['AWS_SECRET_ACCESS_KEY'],
bucket: ENV['AWS_BUCKET']
},
s3_permissions: :private,
path: "/estimates/:id/:version/:filename"
Paperclip.interpolates :document_type do |attachment, style|
attachment.instance.document_type
end
Paperclip.interpolates :version do |attachment, style|
attachment.instance.latest_pdf_version
end
# ...
def generate_pdf
increment!(:latest_pdf_version)
pdf_string = WickedPdf.new.pdf_from_string(
ActionController::Base.new().render_to_string(
:template => '/finance/estimate',
:locals => {
:@estimate => self,
:@billing_client => billing_client,
:@shipping_client => shipping_client,
:@project => project
},
:layout => false,
),
:pdf => estimate_number,
:layout => false,
:page_size => 'Letter',
:lowquality => false,
:handlers => [:erb],
:formats => [:html],
:margin => {:top => 5,
:bottom => 0,
:left => 0,
:right => 0},
:orientation => 'Portrait',
:disposition => 'attachment'
)
tempfile = Tempfile.new(["#{estimate_number}", ".pdf"], Rails.root.join('tmp'))
tempfile.binmode
tempfile.write pdf_string
tempfile.close
self.pdf = File.open tempfile.path
self.pdf_file_name = "#{estimate_number}.pdf"
# Store secure url on the model, valid for 90 days
self.pdf_url = self.pdf.s3_object.url_for(:read, secure: true, expires: 90.days).to_s
save
tempfile.unlink
# Only keep 5 most recent versions
if self.latest_pdf_version > 5
s3 = AWS::S3.new access_key_id: ENV['AWS_ACCESS_KEY_ID'], secret_access_key: ENV['AWS_SECRET_ACCESS_KEY']
s3.buckets[ENV['AWS_BUCKET']].objects["estimates/#{self.id}/#{self.latest_pdf_version - 5}/#{self.estimate_number}.pdf"].delete
s3.buckets[ENV['AWS_BUCKET']].objects["estimates/#{self.id}/#{self.latest_pdf_version - 5}"].delete
end
end
@uriklar
Copy link

uriklar commented Aug 6, 2014

This was perfect! Thanks a lot

@PaulJovanovic
Copy link

Perfect!

@joshuapinter
Copy link

Just as a shortcut and to avoid creating a TempFile, you should be able to just use:

self.pdf = StringIO.new( pdf_string )

This allows you to cut out 5 lines of TempFile related code. 👍

@crystianwendel
Copy link

great tip @joshuapinter!

@micahlisonbee
Copy link

@joshuapinter how do you then name the pdf file?

@AmmadJavaid
Copy link

Thanks for this sharing, worked perfectly (y)

@tquill
Copy link

tquill commented Jul 20, 2017

Anyone know how to use html headers or footers on the PDF with this?

@tquill
Copy link

tquill commented Jul 20, 2017

Got it.

header: {  
  content: ActionController::Base.new().render_to_string(
    template: 'reports/header',
      :layout => 'pdf.html.erb',
      :locals => {
        :@estimate => self,
        :@billing_client => billing_client,
        :@shipping_client => shipping_client,
        :@project => project
      }
    )
  },

@wilfreddas
Copy link

wilfreddas commented Apr 30, 2018

I was able to generate the pdf locally, but when it is uploaded to AWS, it is in different format. I downloaded the file from AWS and looked inside pdf. It is in some kind of different format.

Do I need to save the tempfile to AWS? I know there is a problem with tempfile creation. How to resolve it?
Below is the code

tempfile = Tempfile.new(["#{file_name}", ".pdf"], Rails.root.join('tmp'))
tempfile.binmode
tempfile.write pdf_string
tempfile.close

pdf = File.open tempfile
pdf_file_name = "#{file_name}.pdf"

@file = @user.create(
name: pdf_file_name,
path: pdf,
user_id: @user.id)

@dominiceden
Copy link

@wilfreddas what is the name of your Paperclip attribute on the model? For example, in @micahroberson's example, his is pdf so his model would have the line has_attached_file :pdf in it. That is the attribute you need to set the rendered PDF to. If your Paperclip attribute is pdf, then your code should look like:

@file = @user.create(
name: pdf_file_name,
pdf: pdf,
user_id: @user.id)

@chibuezeayogu
Copy link

perfect! thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment