Ruby on rails, заставляющий пользователя загружать файл tmp

Я создал файл в каталоге tmp со следующим кодом контроллера:

  def download
    file_path = "#{RAILS_ROOT}/tmp/downloads/xxx.html"
    data = render_to_string( :action => :show, :layout => nil )
    File.open(file_path, "w"){|f| f << data }
    flash[:notice] = "saved to #{file_path}"
  end

Это создает файл, который я хотел, в каталоге tmp, и я хочу заставить пользователя загрузить этот файл.

На моем локальном компьютере файл сохраняется по пути, например:

/Users/xxxx/Documents/Sites/xxxx/Website/htdocs/tmp/downloads/xxxx.html

И на живом сервере этот URL будет совершенно другим.

Мне было интересно, как заставить пользователя загрузить этот xxxx.html?

P.S. Если я поставлю...

redirect_to file_path

... на контроллере он просто дает мне маршрут не найден.

Ваше здоровье.


person MintDeparture    schedule 02.05.2011    source источник


Ответы (2)


Взгляните на метод send_file. Это будет выглядеть примерно так:

send_file Rails.root.join('tmp', 'downloads', 'xxxxx.html'), :type => 'text/html', :disposition => 'attachment'

:disposition => 'attachment' заставит браузер загрузить файл, а не отображать его. Установите для него значение «встроенный», если вы хотите, чтобы он загружался в браузере. Если nginx находится перед вашим приложением Rails, вам придется изменить конфигурацию вашей среды (например, environments/production.rb):

# For nginx:
config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect'
person Jack Chu    schedule 03.05.2011

Легко спутать пути к файлам с URL-адресами, но это важное различие. То, что имеет URL-путь /a/b.txt, на самом деле находится в системном пути #{Rails.root}/public/a/b.txt, поэтому вам может потребоваться решить эту проблему, создав оба в тандеме.

Вот как вы можете решить эту проблему:

def download
  base_path = "downloads/xxx.html"

  system_path = File.expand_path("public/#{base_path}", Rails.root)
  url_path = "/#{base_path}"

  File.open(file_path, "w") do |f|
    f.puts render_to_string(:action => :show, :layout => nil)
  end

  flash[:notice] = "saved to #{base_path}"

  redirect_to(url_path)
end

Вы не можете перенаправить на ресурс, который не доступен через ваш веб-сервер, и обычно только вещи в public/ устанавливаются таким образом. Вы можете включить дополнительные пути, если соответствующим образом настроите свой сервер.

Вы также можете обойти весь этот процесс, просто отобразив ответ в виде загружаемого встроенного вложения, если хотите:

render(:action => :show, :layout => nil, :content_type=> 'application/octet-stream')
person tadman    schedule 02.05.2011