Rails 4, How to add an s3 image to wicked pdf - ruby-on-rails

In rails 4, I am using wicked_pdf gem for .pdf file download. I have to add an image inside this pdf, right now image is rendering through wicked_pdf_image_tag in development but in test environment image(s3) is not rendering.
Used Gems are,
gem 'wicked_pdf', '1.0.3'
gem 'wkhtmltopdf-binary', '0.9.9.3'
In initializers,
class WickedPdf
wkhtmltopdf_path = Rails.env.production? ? "#{Rails.root}/bin/wkhtmltopdf-amd64" : "#{Rails.root}/bin/wkhtmltopdf-amd64"
WICKED_PDF = {
:exe_path => wkhtmltopdf_path,
:wkhtmltopdf => wkhtmltopdf_path
}
end
In controller,
respond_to do |format|
format.html {
render :pdf => "sample",
:margin => {:top => 10, :bottom => 10, :left => 10, :right => 10},
:orientation => 'Portrait', # default , Landscape,
:no_background => true
}
end
In views, I have tried to load through
<%= Rails.env.development? ? wicked_pdf_image_tag("img/logo.png") : wicked_pdf_image_tag("#{Rails.root}/public/assets/img/logo.png") %>
<%= Rails.env.development? ? wicked_pdf_image_tag("img/logo.png") : wicked_pdf_image_tag("#{Rails.root}/assets/img/logo.png") %>
<%= image_tag(ActionController::Base.helpers.asset_path('img/logo.png')) %>
How can I load s3 image in pdf file?

You can put the image in a s3 bucket and make it public. After that try it like below. If you use the below code no need to use separate syntax for different environments, it will works for all .Hope it works.
<%= wicked_pdf_image_tag('//s3.amazonaws.com/bucket_name/image.png') %>

I have worked on the similar functionality but using PDFKit gem. But I think rendering logic will be almost similar.
Below is the code where I rendered my partial in controller
def print_batch
batch = Batch.find(params[:id])
respond_to do |format|
format.pdf {
html = render_to_string("_batch",:formats => [:html], layout: false , locals: { batch: batch })
Rails.logger.debug(html.inspect)
kit = PDFKit.new(html)
send_data(kit.to_pdf, :filename => "file_name_#{batch.id}.pdf", :type => 'application/pdf') and return
}
format.html
format.json { render json: {id: batch.id, processed: batch.processed?} }
end
end
In _batch.html.haml. You can see I have used person.s3_logo for rendering the pdf image.
- logo_image_pdf = person.logo.present? ? person.s3_logo : default_credit_logo
- logo_image_html = person.logo.present? ? image_path(Person.logo.thumb('100x100').url) : image_path('default_credit_logo.png')
- logo_image = params[:format] == 'pdf' ? logo_image_pdf : logo_image_html
.bucks
%img.logo{src: logo_image }
In Person.rb model. Anyway we cannot directly render image in PDF file directly from s3. So any gem will first download it in /tmp folder and render it. This is how I have done it in my model file.
def s3_logo
file = open(self.logo.remote_url)
file.path if file
end

Related

Rails + Prawn_rails: How do I add an image to my PDF?

I'm using this gem to use Prawn to create a PDF: https://github.com/Whoops/prawn-rails
However, I can't seem to figure out how to add an image. I've tried pdf.image "path/to/img.jpg but it would say the file is not a recognized format.
I've also looked into this on page 101: http://prawn.majesticseacreature.com/manual.pdf , but it doesn't work.
This is happening in the views:
prawn_document() do |pdf|
pdf.image "#{Rails.root}/public/logo.gif"
end
This throws:
Prawn::Errors::UnsupportedImageType at /admin/purchases/6188.pdf
image file is an unrecognised format
Same happens for a .jpg image
I would do something like this.
gem 'prawn'
bundle install
In your controller.
def controller_method
pdf = Prawn::Document.new
begin
pdf_file_path = "#{Rails.root}/public/output"
full_doc = "#{Rails.root}/public/something.png"
pdf.image full_doc
pdf.start_new_page
pdf.render_file pdf_file_path
rescue Prawn::Errors::UnsupportedImageType
flash[:notice] = "Image unsupported"
redirect_to '/handle'
end
end
Adding an image is easy enough.
def download
#document = Document.find(params[:id])
tmp_file = Tempfile.new(Digest::MD5.hexdigest(rand(12).to_s))
pdf = Prawn::Document.generate(tmp_file.path, :margin => 0, :page_size => "A4", :skip_page_creation => true) do |posting|
posting.start_new_page
posting.image #document.user.logo.path
send_data posting.render, :filename => "whatever.pdf", :type => "application/pdf"
end
end
Obviously #document.user.logo.path could be a literal path, that's just a Paperclip attachment in this case.
UPDATE
If it's a literal path you might need to do something like this:
require "open-uri"
def download
...
posting.image File.open("/path/to/image.jpg")
...
end
It seems the latest prawn (version 1.0.0) has changed. You'll get
undefined method `image=' for #<Prawn::Document
if you try and apply something to pdf.image.
This worked for me:
img = "#{Rails.root}/public/my_lovely_image.png"
Prawn::Document.new(background: img)

wicked_pdf is not rendering header

render :pdf => "file_name",
:layout => 'pdf.html.erb',
:template => 'transactions/show.pdf.erb',
:wkhtmltopdf => WICKED_PDF_BIN,
:show_as_html => true,
:layout => 'pdf.html.erb',
:header => {:html => { :template => 'shared/header.pdf.erb'}}
PDF is generated fine, unfortunately I do not see the header. I can stick the header in the main layout and it works fine too. It seems to me that the header line above is not being processed. The filename 'header.pdf.erb' does not seem to matter. I can point it to a file that does not exist and it throws no error.
This is Mac OS, Rails 3.2.1, ruby 1.9
You may want to simply render the template as a string and assign it to the header's content. Try this out:
header: {
content: render_to_string(template: 'header.pdf.haml')
}
It works well for me.

How to save pdf file inside the public folder using wicked_pdf

Right Now i am using Rails 3.0.0.i already installed the gem wicked_pdf.Now to want to save the pdf file inside the public folder.please help me.
If you need to just create a pdf and not display it:
# create a pdf from a string
pdf = WickedPdf.new.pdf_from_string('<h1>Hello There!</h1>')
# create a pdf from string using templates, layouts and content option for header or footer
WickedPdf.new.pdf_from_string(
render_to_string(:pdf => "pdf_file.pdf", :template => 'templates/pdf.html.erb', :layout => 'pdfs/layout_pdf'),
:footer => {:content => render_to_string({:template => 'templates/pdf_footer.html.erb', :layout => 'pdfs/layout_pdf'})}
# or from your controller, using views & templates and all wicked_pdf options as normal
pdf = render_to_string :pdf => "some_file_name"
# then save to a file
save_path = Rails.root.join('pdfs','filename.pdf')
File.open(save_path, 'wb') do |file|
file << pdf
end
This is top answer on How to convert string in pdf in ruby on rails
And if you aren't against i put one of the answer:
Some services returns pdf as a string like: JVBERi0xLjQKJeLjz9MKNCAwIG9iago8PC9Ue. . .
You can create a pdf file from the sting, with:
f = File.new("/tmp/file.pdf", "w")
f.write(Base64.decode64(invoice[:file]).force_encoding('UTF-8'))
f.close
And then you can open pdf file with AcrobatReader or another pdf reader.
Wish it helps.
Also, you can do this:
render :pdf => 'foo',
:save_to_file => Rails.root.join('public', "foo.pdf"),
:save_only => true

Is there a way for acts_as_flying_saucer to save a file without calling render_pdf?

As the title says I use the Rails gem that works good but I want to separately save pdf's to a folder. Is there a way to do this without calling render_pdf?
This is what does not work:
render_pdf :template => 'caseprinttemplates/create_pdf_to_print.erb', :pdf_file => "/home/mattias/www/Inkasso/public/uploadedfiles/" + results[:title]
redirect_to new_interventionreminder_path(:case_id => #interventionreminder.case_id, :saved => "1")
return
This does work on another page:
render_pdf :template => 'caseprinttemplates/create_pdf_to_print.erb', :layout => nil, :send_file => { :filename => "samladutskrift.pdf"}
The acts_as_flying_saucer plugin is just a wrapper around the Flying Saucer java library. In the source, you can see that only a single wrapper method is defined: render_pdf().
https://github.com/dagi3d/acts_as_flying_saucer/blob/master/lib/acts_as_flying_saucer_controller.rb
You can, however, use render_pdf() to render to a file, like the examples found here:
# Renders the template located at '/foo/bar/pdf.html.erb' and stores the pdf
# in the temp path with a filename based on its md5 digest
render_pdf :file => '/foo/bar/pdf.html.erb'
# renders the template located at 'app/views/foo.html.erb' and saves the pdf
# in '/www/docs/foo.pdf'
render_pdf :template => 'foo', :pdf_file => '/www/docs/foo.pdf'
# renders the 'app/views/foo.html.erb' template, saves the pdf in the temp path
# and sends it to the browser with the name 'bar.pdf'
render_pdf :template => 'foo', :send_file => { :filename => 'bar.pdf' }

Difficulty with send_data in Ruby on Rails in conjunction with Spreadsheet plug-in

I have a function in a controller that takes in some specifications and generates a report on them. This function user_report is called in a view:
< %= submit_to_remote 'submit-button', "Export Report to Excel", :url => { :controller => :reports, :action => :user_report, :print_state => 'print'} % >
In reports_controller I use the Spreadsheet plugin to generate an Excel file within the user_report function. I want to use send_data to stream the file to the user without creating it on the server first. The research I've done shows that using StringIO is the way to go, as shown below. Frustratingly, nothing happens when I call send_data. The plugin seems to work well creating a file and saving it on the server, but does nothing when I use send_file, suggesting that the problem doesn't lie in the plugin. But then what am I doing wrong with send_file/send_data?
The function itself looks like this:
def user_report
if request.post?
unless params[:reports][:userid].blank?
#userid=params[:reports][:userid]
end
if params[:print_state]=='print'
report = Spreadsheet::Workbook.new
info = report.create_worksheet :name => 'User Information'
info.row(1).push 'User ID', #userid
#outfile = "Report_for_#{#userid}.xls"
require 'stringio'
data = StringIO.new ''
report.write data
send_data data.string, :type=>"application/excel", :disposition=>'attachment', :filename => #outfile
end
respond_to do |format|
format.js { }
end
end
end
The log file reads
2010-10-18 14:13:59 INFO -- Sending data Report_for_jjohnson.xls
but no download begins in-browser. I've succeed in using send_data on this app before, which is confusing.
I'm using Rails v2.3, Ruby v1.8.7, and Spreadsheet v6.4.1 at spreadsheet.rubyforge.org.
Just change the line:
send_data data.string, :type=>"application/excel", :disposition=>'attachment', :filename => #outfile
to:
send_data data.string.bytes.to_a.pack("C*"), :type=>"application/excel", :disposition=>'attachment', :filename => #outfile
Even though I dont like to write and delete , but with spreadsheet seems like the only solution.
# write the file
book.write "Employee_History_#{ params[:id]}.xls"
# send the file
send_file "Employee_History_#{ params[:id]}.xls", :type => "application/vnd.ms-excel", :filename => "data.xls", :stream => false
# and then delete the file
File.delete("Employee_History_#{ params[:id]}.xls")
For someone looking at this in (or after) 2022, a possible solution to this would be to use Axlsx Gem. The interface provides a method for converting it to a StringIO object. (From Axlsx Documentation)
#serialize to a file
p = Axlsx::Package.new
# ......add cool stuff to your workbook......
# Serialize to a stream
s = p.to_stream()
send_data(
s.read,
:type => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
:disposition => 'attachment',
:filename => #filename
)

Resources