I use prawn-rails.
I have a show.pdf.prawn view.
I would like to have an action to download this pdf.
I tried the following:
def download
send_data(
show,
filename: "#{custom_name}.pdf",
type: 'application/pdf'
)
end
What it does, is download something called #{custom_name}.pdf but I m unable to open it (falied to load PDF document).
Having it changed to
def download
send_file(
show,
filename: "#{custom_name}.pdf",
type: 'application/pdf'
)
end
I am getting
no implicit conversion of true into String
Please advice.
Should work:
send_data render_to_string("show"), filename: "#{custom_name}.pdf",
type: 'application/pdf'
Also you can use prawnto_2 library:
gem "prawnto_2", require: "prawnto"
and then simply render in the controller action:
def show
respond_to do |format|
format.pdf {
prawnto inline: false,
filename: "#{custom_name}.pdf",
prawn: {} # prawn settings here
}
end
end
But I'm not sure how this library is currently maintained, however still works with Rails 4.2.x.
How about:
def download
response.headers['Content-Disposition'] = 'attachment; filename="' + custom_name + '.pdf"'
render :show, mime_type: Mime::Type["application/pdf"]
end
Related
In my rails app, I am creating an API that accepts order details from other devices and generates pdf which is then uploaded to the AWS.I am using wicked_pdf gem to generate the pdf and aws-sdk to upload data to Aws. The controller code is as follows.
def order_invoice
response = Hash.new
result = Hash.new
if params[:order] && params[:order][:txnid] &&
params[:no_of_copies] && params[:order][:total_amount]!= 0
#order = params[:order]
...
#no_of_copies = params[:no_of_copies]
invoice = create_pdf
response['result'] = invoice
response.merge! ApiStatusList::OK
else
response.merge! ApiStatusList::INVALID_REQUEST
end
render :json => response
end
def create_pdf
pdf = WickedPdf.new.pdf_from_string(
render_to_string(template: 'invoices/generate_invoice.pdf.erb'))
send_data(pdf, filename: params[:order][:txnid] + ".pdf" ,
type: 'application/pdf',
disposition: 'attachment', print_media_type: true)
save_path = Rails.root.join('pdfs', #order['txnid'] + ".pdf")
File.open(save_path, 'wb') do |file|
file << pdf
filename = #order['txnid'] + ".pdf"
end
file_name = #order['txnid'] + ".pdf"
upload = Invoice.upload(save_path, file_name)
end
While generating and uploading the pdf I get the following error
AbstractController::DoubleRenderError in Api::V0::InvoiceApiController#order_invoice
Render and/or redirect were called multiple times in this action. Please note that you may only call render OR redirect, and at most once per action. Also note that neither redirect nor render terminate execution of the action, so if you want to exit an action after redirecting, you need to do something like "redirect_to(...) and return".
I need to give the link of the uploaded pdf as response. I know the error is because of using two renders here. However I dont know how to overcome the error. Can anyone help me to tweak and correct the code. Newbie in rails and api's.
This is because you render repsonse 2 times:
via send_data in #create_pdf
via render :json => response in action
UPD:
After discussion, we came to this - you don't need content of the file in your response, only link to AWS.
So, to fix this just remove your send_file call:
def create_pdf
# render_to_string doesn`t mean "render response",
# so it will not end up "double render"
pdf = WickedPdf.new.pdf_from_string(
render_to_string(template: 'invoices/generate_invoice.pdf.erb'))
# send_file renders response to user, which you don't need
# this was source of "double render" issue
# so we can just remove it
save_path = Rails.root.join('pdfs', #order['txnid'] + ".pdf")
File.open(save_path, 'wb') do |file|
file << pdf
filename = #order['txnid'] + ".pdf"
end
file_name = #order['txnid'] + ".pdf"
upload = Invoice.upload(save_path, file_name)
end
I'm facing an issue of how to zip the excel sheet generated through gem 'axlsx_rails'. For example:
class SampleController < ApplicationController::Base
def export
if params[:zip]
xxxx
else
render xlsx: 'export', filename: filename, disposition: 'attachment'
end
end
end
In the above example, right now the end user is able to download the excel sheet but if the end user requests a zip file of excel sheet, how can we do that. Because of code in 'else' block the end user is able to download the excel sheet. What I have to do if the user wants the excelsheet to be zipped before download. If you need any further info, plz let me know. Thanks
This is untested code, but try using Zip::ZipOutputStream:
def export
if params[:zip]
compressed_filestream = Zip::ZipOutputStream.write_buffer do |zos|
content = render_to_string xlsx: 'export', filename: filename
zos.put_next_entry(filename)
zos.print content
end
compressed_filestream.rewind
send_data compressed_filestream.read, filename: 'export.zip', type: 'application/zip'
else
render xlsx: 'export', filename: filename, disposition: 'attachment'
end
end
If it doesn't work, create an issue on Github, and after we get it working we can add it to the documentation.
Currently I am generating a pdf using prawn gem of rails. pdf is generated when user hit on this action
def print_pdf
#user = User.find(params[:id])
#details = #user.details_data
respond_to do |format|
format.pdf do
pdf = PrintDetailsPdf.new(#user, view_context, #details)
send_data pdf.render, filename: "#{#user.id}.pdf",
type: 'application/pdf',
disposition: 'inline'
end
end
end
In above action, I generate the pdf and show it in browser and it works perfectly. But I want to show the pdf in browser and also save the pdf at server in public/user_details directory. How can I do that?
There are some good gems that help in file uploading and saving. Here is a list of these gems. Paperclip and Carrierwave are the most popular options.
You could also implement it from scratch. Rails has built-in helpers which make it easy to roll your own solution.
pdf_content = *Content you want to save in the file*
File.open(Rails.root.join('public', 'user_details', filename), 'wb') do |file|
file.write(pdf_content.read)
end
It depends on the complexity of what you want to achieve, but this is totally sufficient for easy file saving tasks. Go here to find more information.
You could do this
pdf_string = render_to_string :template => 'template', :layout => false
File.open("public/userfiles/example.pdf", 'wb') { |
f| f.write(pdf_string) }
end
Render the template to string and then create a file and write that pdf to it..
This should help
I am using tinymce-rails-imageupload plugin with dragonfly.
When the image is uploaded via separate form in popup window, it behaves as expected (save image in datastore).
But when the user drag-drop or paste image into TinyMCE, the imageupload plugin allows it. I tried to find a way to disable this behavior, but apparently there is no straightforward way to disable allowing image upload, while disallowing the past/drag-drop behavior. So I gave up on that..
Now, I'm trying to save BASE64 image in TinyMCE's content.
In controller:
def store_file
#image = Resource.new :res_image => params[:file]
#image.save
render json: {
image: {
url: #image.res_image.remote_url
}
}, content_type: "text/html"
end
def create
#entry = Entry.new(params[:entry])
# iterate through tinyMCE field params[:entry][:message]
# if image tag is found
# if value of src tag starts with "data:"
# then replace it with the output of
# Resource.create_image_from_base64(extracted_base64_value)
# end if
# end if
# end iteration
begin
#entry.save!
flash[:success] = "Entry was successfully created."
redirect_to entries_path
rescue Mongoid::Errors::Validations => e
render :action => "new"
end
end
In Resource model, I would have something like:
image_accessor :res_image
field :res_image_uid, type: String
field :res_image_name, type: String
def create_image_from_base64(base_64_encoded_data)
file = File.open('temp.png', 'wb') do|f|
f.write(Base64.decode64(base_64_encoded_data))
end
resource = # create Resource with temp file
file.close
resource.res_image.remote_url
end
Questions:
How to create "Entry with file"?
Is there a better approach for handling pasted/dragged-droped base64 images in TinyMCE with dragonfly?
Even if it is an old question:
look at this: https://groups.google.com/forum/#!topic/dragonfly-users/xNWIwZf5-_Y
I have used the following syntax to generate a pdf file:
Prawn::Document.generate("#{RAILS_ROOT}/public/pdf/generate.pdf") do
pdf.text "hello"
end
But when I look for the file within the /public/pdf/ folder, I dont find any file.
Well my controller code for this is
def generate
respond_to do |format|
format.pdf{ render :file => "#{RAILS_ROOT}/public/pdf/generate.pdf"}
end
end
It could be something else, but the code supplied doesn't seem to work:
Prawn::Document.generate("x.pdf") do
pdf.text "Hello"
end
gives me
NameError: undefined local variable or method `pdf' for #<Prawn::Document:0x352b6e4>
from c:/ruby/lib/ruby/gems/1.8/gems/prawn-core-0.8.4/lib/prawn/graphics/color.rb:72:in `method_missing'
from (irb):3
You should be able to see if you're getting something similar in your log file.
I think the pdf. is not needed:
Prawn::Document.generate("x.pdf") do
text "Hello"
end
ruby - 1.9.3
rails - 3.2
way 1
create new project in rails
rails new prawn_sample
you can find gem file inside project folder, add prawn gem.
gem 'prawn'
then bundle install
now, install prawnto plugin
rails plugin install git#github.com:forrest/prawnto.git
For sample data to display, let’s create a Book model with title,author and description.
rails generate scaffold book title:string author:string description:text
then
rake db:migrate
now start the server and enter sample data's to test
so,
rails s
localhost:3000/books
here enter the required amount of data's
next
Let’s get started with something simple and add a pdf version of the show action. Open up the books controller and add format.pdf
def show
#book = Book.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => #book }
format.pdf { render :layout => false }
end
end
create the show.pdf.prawn file inside app/views/books. For now, lets have hello world
pdf.text "Hello World!"
visit
http://localhost:3000/books/1
http://localhost:3000/books/1.pdf
you successfully generated PDF.
Let’s make the view specific to the books.
in show.pdf.prawn
pdf.font "Helvetica"
pdf.text "Book: #{#book.title}", :size => 16, :style => :bold, :spacing => 4
pdf.text "Author: #{#book.author}", :spacing => 16
pdf.text #book.description
now you see some text with format specified above . Browse more for format you required.
way 2
Gemfile
gem 'prawn'
/config/initializers/mime_types.rb
Mime::Type.register "application/pdf", :pdf
AuditsController
def show
#audit = Audit.find(params[:id])
respond_to do |format|
format.html
format.pdf do
pdf = Prawn::Document.new
pdf.text "This is an audit."
send_data pdf.render, type: "application/pdf", disposition: "inline"
end
end
end
Not sure what version of Prawn you're using, but this worked for me:
pdf = Prawn::Document.new(background: img, :page_size => "LETTER", :page_layout => :landscape)
pdf.render_file File.join(Rails.root, "app/pdfs", "x.pdf")
I think you're missing the pdf.render_file line that actually creates the file.