Given the controller :
class MyController < Nitro::Controller def download f = File.open('/etc/passwd') # ??? end end
What should I put at # ??? to send /etc/passwd to the user ? (high security :-))
(2 attempts)
zimbatm answered:
The following code is a possible solution altrough I would like to avoid putting custome headers. The force-download header have only been tested in Firefox 1.5 under Linux.
Note: I use the streaming capabilities of Nitro to avoid big memory consuption.
require 'nitro/cgi/stream' class MyController < Nitro::Controller def download f = File.open('/etc/passwd') @context.response_headers["Content-Disposition"] = 'attachment; file="passwd.txt"' @context.response_headers["Content-Transfer-Encoding"] = 'binary' stream f end end
Tyche answered:
I am using this. I put in /nitro/cgi/sendfile.rb
require 'nitro/render' module Nitro module Render # Send a file download to the client. # # Like render and redirect, the action is exited upon calling # # [+fname+] That name of the file # [+path+] Specifying true mean fname contains the full path. # The default, false, uses Server.public_root as the path. # # [+return+] true on success, false on failure # # === Examples # # require 'nitro/cgi/sendfile' # class MyController < Nitro:Controller # def download(fname) # sendfile(fname) # end # end # # class MyController < Nitro:Controller # def download() # sendfile('/etc/password', true) # end # end def sendfile(fname=nil, fullpath=false) fname = fullpath ? fname : "#{Server.public_root}/#{fname}" f = File.open(fname, "rb") @context.response_headers["Cache-control"] = 'private' @context.response_headers["Content-Length"] = "#{File.size?(f) || 0}" @context.response_headers["Content-Type"] = 'application/force-download' @context.out = f raise RenderExit end end end