Rails 3: Sending tempfiles for download

When you create a temporary file (e.g. to store a generated Excel sheet) and try to send it to the browser from a controller, it won't work by default. Take this controller action:

class FoosController < ApplicationController
  def download
    file = Tempfile.new('foo')
    file.puts 'foo'
    file.close
    send_file file.path
  end
end

Accessing this controller action will usually raise a 404 not found in the browser and the Apache log will say:

The given path was above the root path: xsendfile: unable to find file: /tmp/foo20110721-28050-1h104da-0

The reason for this is that Rails 3 uses X-Sendfile for file downloads and Apache is only allowed to transfer files from a whitelist of paths that should not include /tmp.

One solution for this is to save the tempfile in your project directory's tmp instead:

file = Tempfile.new('foo', 'tmp')

Note that depending on your setup, you might need to change that file's permissions so Apache can read it.

Henning Koch Almost 13 years ago