7

我正在使用Rails 3.1.0.rc8和Chromium 15.0.874.102。in rails,無法覆蓋內容配置文件名

我想設置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"} 

鉻網絡檢查工具,我看到下面的我的迴應標題:

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

如果我將Content-Type更改爲foo/bar之類的東西,我會在網絡檢查器工具中看到更改。無論我如何設置filename,它仍然是index.csv

感謝, 最大

+0

你有正確的設置視圖嗎? – baol

+0

視圖呈現預期,如果這就是你的意思;下載文件的內容看起來像我想要的 – maxenglander

回答

11

按照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}\"" 
+0

請注意,如果文件名本身可以包含引號,則需要將它們轉義 - filename.gsub(/「/,'\\」')' – gmcnaughton

2

我發現我的團隊正在使用csv_builder寶石,它允許您通過在控制器設置@filename調整下載的文件的名稱。對於任何能解釋我爲什麼會得到OP中描述的行爲的人,仍然會給予正確的答案。

1

我看不到你在哪裏實際發送/渲染輸出......是在一個.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 

在我的控制器,它工作得很好。也許標題被模板渲染破壞了。

0

我個人不會使用render這類內容 - 我更喜歡使用send_data。這裏是一個例子:

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