Ruby on rails, заставляющий пользователя скачивать tmp файл - PullRequest
3 голосов
/ 03 мая 2011

Я создал файл в каталоге 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?

PS Если я добавлю ...

redirect_to file_path

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

Приветствия.

Ответы [ 2 ]

4 голосов
/ 03 мая 2011

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

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

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

# For nginx:
config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect'
3 голосов
/ 03 мая 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')
...