【问题标题】:in rails, unable to override content-disposition filename在 Rails 中,无法覆盖内容配置文件名
【发布时间】:2011-11-28 17:43:11
【问题描述】:

我正在使用 Rails 3.1.0.rc8 和 Chromium 15.0.874.102。

我想设置 CSV 下载的文件名。我正在关注这个SO solution,但发现自己无法修改Content-Disposition 标头的filename

这是我的代码:

module ActionController 
  module CSVHelper

    def render_csv options={}
      if request.env['HTTP_USER_AGENT'] =~ /msie/i
        headers['Pragma'] = "public"
        headers['Content-Type'] = "text/plain"
        headers['Cache-Control'] = "no-cache, must-revalidate, post-check=0, pre-check=0"
        headers['Expires'] = "0"
      else
        headers['Content-Type'] = "text/csv"
      end

      filename = generate_filename options.delete(:basename)
      headers['Content-Disposition'] = "attachment; filename=#{filename}"
    end

    def generate_filename basename=nil, suffix="csv"
      filename = basename || params[:action]
      filename << ".#{suffix}"
      filename
    end

  end
end    

在我的控制器中:

respond_to do |format|
  format.html
  format.csv do
    render_csv(:basename => "my_filename")
    Rails.logger.debug "HEADERS: #{headers.to_s}"
  end
end  

在我的日志中:

[2011-11-28 12:25:49.611] DEBUG - HEADERS: {"Content-Type"=>"text/csv", "Content-Disposition"=>"attachment; filename=my_filename.csv"}

在 Chromium 网络检查器工具中,我在响应标头中看到以下内容:

Content-Type: text/plain
Content-Disposition: attachment; filename=index.csv

如果我将Content-Type 更改为foo/bar,我会在我的网络检查器工具中看到更改。无论我将filename 设置为什么,它仍然是index.csv

谢谢, 最大

【问题讨论】:

  • 您的视图设置正确吗?
  • 视图按预期呈现,如果这就是您的意思;下载文件的内容看起来像我想要的

标签: ruby-on-rails-3 http-headers chromium fastercsv content-disposition


【解决方案1】:

根据Content-Disposition section of the appendices to the HTTP/1.1 specification,文件名必须是带引号的字符串

   filename-parm = "filename" "=" quoted-string
   ...

一个例子是

   Content-Disposition: attachment; filename="fname.ext"

因此您可能需要进行以下更改(注意引号):

headers['Content-Disposition'] = "attachment; filename=\"#{filename}\""

【讨论】:

  • 请注意,如果文件名本身可以包含引号,则需要对其进行转义 - filename.gsub(/"/, '\\"')
【解决方案2】:

我发现我的团队正在使用csv_builder gem,它允许您通过在控制器中设置@filename 来调整下载文件的名称。仍将向任何能够解释为什么我会遇到 OP 中描述的行为的人奖励正确答案。

【讨论】:

    【解决方案3】:

    我个人不会将render 用于此类内容 - 我更喜欢使用send_data。这是一个例子:

    send_data data, :type => 'text/csv', :disposition => 'attachment; filename=my_file_name.csv'
    

    【讨论】:

      【解决方案4】:

      我看不到您实际发送/呈现输出的位置...是在 .csv.erb 文件中还是什么?或者使用 csv_builder 作为其他答案?这可能是诀窍。

      我想出了同样的方法来渲染 .xlsx 输出。一旦我将文件放在磁盘上,我就可以这样做:

      def example
        respond_to do |format|
          format.xlsx do
            path = some_method_generating_xlsx_file
            headers['Content-Disposition'] = "attachment; filename=test.xlsx"
            render :text => File.binread(path), :content_type => XLSX_MIME_TYPE
          end
        end
      end
      

      在我的控制器中,它工作得很好。也许标题被模板渲染破坏了。

      【讨论】:

        猜你喜欢
        • 2017-09-20
        • 2021-11-11
        • 1970-01-01
        • 2010-09-20
        • 2014-05-31
        • 2018-11-29
        • 1970-01-01
        • 2013-10-18
        • 1970-01-01
        相关资源
        最近更新 更多