Clarification needed for what send_data disposition: "inline" does - ruby-on-rails

I am migrating some codebase from an old rails app into a new one and one of the controller methods has this in it.
send_data(render_compare_chart(#projects, start_date, end_date),
:disposition => 'inline', :type => 'image/png' )
I looked up the definition of what send_data does and I get it except for this part for the disposition option.
:disposition Suggests to the browser that the file should be displayed inline
What exactly does that mean in the context of the code above? Am I supposed to see an image file rendered on the browser or not? Currently I don't see anything that remotely looks like what I'm supposed to be seeing. I don't know what I'm looking for here?
Inside the render_compare_chart method there is some imagemagick stuff going on so I'm wondering if I should be seeing something or not. Can someone clarify what this inline option means? Thanks.

Related

Ruby Sinatra: redirect page not working?

The problem lies in the following code ("routes.rb").
post 'download_csr' do
file_name = File.dirname(__FILE__) + '/cert.csr'
File.open(file_name, 'w') do |f|
f.write params[:csr]
end
send_file file_name, :disposition => 'attachment'
erb :load_certificate, :locals => { :csr => 'cert.csr' }
end
The flow is this: the user clicks a button on a form, then a file is written and downloaded to local system, then it goes to another page (i.e., "load_certificate.erb").
However, what really happens is that after the file is downloaded, it doesn't go to the next page. But if I comment out "send_file", it will go to the next page. So how to address this? Thanks a lot!
One more thing: it would be good to make sure the file is actually downloaded before going to the next page (because when send_file pops out a window, the user can choose "cancel"). Some time-out mechanism may not work here.
#Soup's link is a good one to read. With regard to Sinatra, send_file calls halt, which ends the request (in this case by sending the status and the file). Nothing will be processed after a halt.

Is there a way to have a resque job push a generated pdf directly to the browser?

I need to have a system where a PDF is generated dynamically, asynchronously, and directly pushed to the browser, no disk storage is available. Getting resque to use prawn seems easy, its taking that data and sending it to the browser without storing it somewhere first, I can't find anything online. I thought about Faye, but can Faye handle pushing a PDF to the browser?
I've done this before in .net where i have an iframe's src attribute set to a service that returns a stream. The service aslo flips the http header to content-inline so that the browser doesn't try to download it but instead will try to render it inline. If you try to do this it wont work if the browser doesn't have a pdf plugin (must modern ones will but you always have that guy using IE6 yet) I don't know a lick of ruby but think you should be able to do something similar, or at least but an iframe on a page that targets a service written in something else.
u can use "PDFkit" for it.
the sample code is
def some_action
...
respond_to do |format|
format.html
format.pdf do
generate_pdf(file.html.haml, :css => [array of css file names that need to be added])
end
end
end
in application controller -
def generate_pdf(template, options={})
html = render_to_string(template, :layout => false)
kit = PDFKit.new(html, :orientation => 'Landscape')
kit.stylesheets << "#{Rails.root}/app/assets/stylesheets/default_css1.css"
kit.stylesheets << "#{Rails.root}/app/assets/stylesheets/default_css2.css"
# Add CSS
if options[:css]
options[:css].each do |css|
kit.stylesheets << "#{Rails.root}/app/assets/stylesheets/#{css}.css"
end
end
send_data(kit.to_pdf, :filename => 'latest.pdf', :type => 'application/pdf', :disposition => 'inline')
end
How big those PDFs are? Your database has BLOB columns (if you don't have storage, you are not using SQLite...) and you can store the resulting PDF in it.
Or you can store the resulting PDF in the Redis DB. Or save it in S3.
On the other end, the browser will be polling (with ajax) every now and then to know whether the PDF is complete, and as soon as it is ready it will download it and show it to the user.

Returning files from rails

Beginner rails question: How does one return a file from a controller in rails?
I'm familiar with returning/rendering JSON objects. However I've never returned/rendered a file w/ an arbitrary extension.
From reading around SO it sounds like render :nothing => true could help. I'm just looking for some guidance or relevant documentation.
You can use the built-in rails send_file or send_data method.
To stream a file (e.g. for a file proxy endpoint), use send_file:
send_file("#{RAILS_ROOT}/path/to/file/on/server",
:filename => "client-suggested-filename",
:type => "mime/type")
To stream generated data (e.g. for a generated pdf), use send_data:
send_data(your_data,
:filename => "client-suggested-filename",
:type => "mime/type")
The file extension and mime type don't have to match up, but they probably should just to conform to end user expectations. For example, if you are sending with a mime type of application/pdf, you should really set the :filename to something.pdf.
If you're not sure what the mime type is for the file you are sending, you can check this wikipedia page or use the mime-types gem. (Or if you are reading from a database that stores the mime type, use that).

rails 3 and PDFkit

I'm trying to follow this tutorial.
When I'm adding .pdf to my url it does nothing. My controller has:
respond_to :html, :pdf.
My mime type has been declared.
I tried this too:
respond_to do |format|
format.html
format.pdf {
html = render_to_string(:layout => false , :action => "www.google.fr")
kit = PDFKit.new(html)
send_data(kit.to_pdf, :filename => "candidats.pdf", :type => 'application/pdf')
return # to avoid double render call
}
end
but it does not work and I don't get errors. My browser keep waiting for localhost, but nothing happens.
So how should I try to use pdfkit ?
edit 2 :
According to my rails' logs, rails render successfully the HTML. I saw this in the .log, rails doesn't send it to webrick nor to my browser. And my browser keeps waiting, and waiting and nothing happen. I only have little pictures here.
edit 3 : My webrick server seem unable to respond to other request, once he starts getting a .pdf version of my url, any ideas ?
edit 4 :
I am using rails 3.1, wkhtmltopdf 0.9.5 (windows installer) and pdfkit 0.5.2
I found a better way to access my .pdf urls even in developpement mode.
# Enable threaded mode
config.threadsafe!
# Code is not reloaded between requests
#config.cache_classes = true
Config.cache_classes is a comment, cause i had some problems when it wasn't. This way pdfkit works wonder even with rails 3.1. But, you don't reload code between requests.
That's not really a problem, cause you first work on your html, and you switch configuration, in order to check the pdf result. This way you don't have to bother about your production database.
Thanks to another stack overflow answer I got part of solution.
This works:
html = '<html><body>Toto de combats</body></html>'
#pdf = PDFKit.new(html)
send_data #pdf.to_pdf, :filename => "whatever.pdf",
:type => "application/pdf",
:disposition => "attachement"
You can replace attachement by inline, so the pdf is displayed in your browser.
In the stack overflow answer I spoke about (I don't remember the link), the .to_pdf was missing, but is mandatory. Otherwise PDF reader doesn't recognize it.
I'm trying to get this work with a .pdf url.
Edit 3:
My problem with .pdf urls is solved. known issue with rails 3.1, but google was unable to find them.
explanation : explanation
Workaround (hadn't tryied yet). workaround

Direct downloading a xls file without writing it to the directory by Spreadsheet gem

I am using this Spreadsheet gem to export xls file.
I have the following codes in my controller:
def export
#data = Data.all
book = Spreadsheet::Workbook.new
sheet = book.create_worksheet :name => "data"
contruct_body(sheet, #data)
book.write "data.xls"
end
In this way, I can fill in the data and save it in the root directory.
But I want to download it instead of save it. How could I modify the code so that the user prompted to select his local directory to save the file? (better if without saving a copy in the server side)
Please help!
You can send it to the browser without saving it as a local file at all as follows
spreadsheet = StringIO.new
book.write spreadsheet
send_data spreadsheet.string, :filename => "yourfile.xls", :type => "application/vnd.ms-excel"
You could try this code
book.write "data.xls"
send_file "/path/to/data.xls", :type => "application/vnd.ms-excel", :filename => "data.xls", :stream => false
# and then delete the file
File.delete("path/to/data.xls")
Passing :stream => false to send_file will instruct Rails to copy the entire file into memory before streaming, so using File.delete immediately after send_file would be fine since send_file returns immediately without waiting for the download to complete. Having said that, with very large files you may see some memory bottle necks depending on the amount of memory available.
HTH
I understand this is insanely old, but I was looking for it so someone else might be.
This is the answer. (I'm using Sinatra.)
https://github.com/zdavatz/spreadsheet/issues/125#issuecomment-370157753
The case happen on mybody.
I used the ajax request by remote::true to export excel file, nothing display on browser without any error message on console.
Delete the remote params from the form, it works well.

Resources