Ruby on rails,强制用户下载tmp文件

时间:2011-05-02 20:29:31

标签: ruby-on-rails file redirect download 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

在实时服务器上,这个网址将完全不同。

我想知道的是如何强制用户下载此xxxx.html?

P.S。 如果我放一个......

redirect_to file_path

......在控制器上,它只给我一条未找到的路线。

干杯。

2 个答案:

答案 0 :(得分:4)

查看send_file方法。它看起来像这样:

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

:disposition =&gt; 'attachment'将强制浏览器下载文件而不是渲染文件。如果要在浏览器中加载,请将其设置为“内联”。如果nginx在你的Rails应用程序前面,那么你将不得不修改你的环境配置(即.environment / production.rb):

# For nginx:
config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect'

答案 1 :(得分:3)

将文件路径与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

您无法重定向到未通过Web服务器公开的资源,通常只有public/中的内容以这种方式设置。如果您相应地配置服务器,则可以包含其他路径。

如果您愿意,您还可以通过简单地将响应呈现为可下载的内联附件来支持整个过程:

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