7

Sto utilizzando Rails 3.1.0.rc8 e Chromium 15.0.874.102.in rotaie, impossibile eseguire l'override del contenuto nome file

Desidero impostare il nome file di un download CSV. Sto seguendo questo SO solution, ma non riesco a modificare l'filename dell'intestazione Content-Disposition.

Ecco il mio codice:

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  

E nel mio controller:

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

nel mio ceppo:

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

In strumento di rete ispettore di cromo, vedo quanto segue in le mie intestazioni di risposta:

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

Se cambio lo in foo/bar, vedo che la modifica è avvenuta nello strumento di ispezione della rete. Indipendentemente da ciò che ho impostato su filename, rimane index.csv.

Grazie, Max

+0

hai la visualizzazione corretta? – baol

+0

la vista esegue il rendering come previsto, se questo è ciò che intendi; il contenuto del file scaricato sembra che io voglia – maxenglander

risposta

11

Secondo il Content-Disposition section of the appendices to the HTTP/1.1 specification il nome del file deve essere una stringa citato:

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

Un esempio è

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

Quindi, probabilmente è necessario apportare la seguente modifica (nota le virgolette):

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

Si noti che se il nome file stesso può contenere virgolette, è necessario sfuggire a esse - 'filename.gsub (/" /, '\\ "')' – gmcnaughton

2

ho scoperto che la mia squadra sta usando il csv_builder gemma, che permette di regolare il nome del file scaricato impostando @filename nel controller. Otterremo comunque la risposta corretta a chiunque possa spiegare perché stavo ottenendo il comportamento descritto in OP.

1

Non vedo dove si sta effettivamente inviando/rendendo l'output ... È in un file .csv.erb o qualcosa del genere? O usando csv_builder come altra risposta? Questo potrebbe essere il trucco.

Mi è venuta la stessa cosa per il rendering di un output .xlsx. Una volta ho avuto il file su disco, ho potuto fare questo:

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 

nel mio controller, e ha funzionato bene. Forse le intestazioni venivano sbalordite dal rendering del modello.

0

Personalmente non uso render per questo tipo di contenuto - Preferisco usare send_data. Ecco un esempio:

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