>
> I''m attempting to use send_file to send an image file from
> public/images. The file is world readable.
>
> I''ve tried supplying the full path, but it still can''t
seem to find
the> file. Here is the code that calls send_file:
I don''t think I would do this on purpose, if the image is really in
public. If you want to change the image name at run time, I would
instead generate an <img> tag in the view, which the browser will then
download (per the setting of the user).
Otherwise, if you wish to send content that is *not* inside your web
(e.g. in /public or below) then you might do something like:
Config/routes.rb
# Force all requests for /protected/whatever to the render_static
method.
# Static content control
map.connect ''/protected/*path'', :controller =>
''protected'',
:action =>
''render_static''
def render_static
# see routes.rb. A map is made so that the URL is
# visible as params[:path]
requested_file = params[:path].to_s
safe, opf = safe_to_send?(requested_file)
if safe
# compute the mime type and send the content here
# This should be made much more concise (a hash lookup)
# and extended to cover more mime types
if requested_file =~ /\.pdf$/ then
apptype = "application/pdf"
elsif requested_file =~ /\.ppt$/ then
apptype = ''application/vnd.ms-powerpoint''
elsif requested_file =~ /\.swf$/ then
apptype = ''application/x-shockwave-flash''
else
apptype = ''octet/stream''
end
send_file opf, :type=> apptype, :disposition=> "inline"
end
end
protected
def safe_to_send?(requested_file)
# Absolute file location. Beware that funny business with RAILS
ROOT
# (e.g. symbolic links) could throw this off
output_base = File.expand_path RAILS_ROOT
output_file = File.expand_path output_base + ''/secret/'' +
requested_file
# Attempt to foil directory traversal attacks
# make sure that output base is the beginning portion of output_file
# I *think* rails makes this check unnecessary, but hey...
result = false
if output_file.index(output_base) == 0 and File.exists?(output_file)
result = true
end
return result, output_file
end
Note that I''m being paranoid about traversal attacks. I believe rails
already deals with all of the . and .. stuff when the URL is submitted
by the browser, however, I could be wrong.
In this case, the protected content is in a subdirectory called
''secret'', which is one level below the main root of the rails
app.
Regards,
Rich