7

J'utilise Rails 3.1.0.rc8 et Chromium 15.0.874.102.dans les rails, impossible d'ignorer le nom de fichier content-disposition

Je souhaite définir le nom de fichier d'un téléchargement CSV. Je suis ce SO solution, mais je me trouve incapable de modifier le filename de l'en-tête Content-Disposition.

Voici mon code:

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  

Et dans mon contrôleur:

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

Dans mon journal:

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

Dans l'outil Inspecteur de réseau de chrome, je vois ce qui suit dans mes en-têtes de réponse:

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

Si je change le Content-Type à quelque chose comme foo/bar, je vois le changement venir à travers dans mon outil d'inspecteur de réseau. Peu importe ce que je définis le filename, il reste index.csv.

Merci, Max

+0

Avez-vous configuré la vue correctement? – baol

+0

la vue s'affiche comme prévu, si c'est ce que vous voulez dire; le contenu du fichier téléchargé ressemble à celui que je veux – maxenglander

Répondre

11

Selon le Content-Disposition section of the appendices to the HTTP/1.1 specification le nom du fichier doit être une chaîne entre guillemets:

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

Un exemple est

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

Alors vous avez probablement besoin de faire le changement suivant (note les guillemets):

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

Notez que si le nom de fichier lui-même peut contenir des guillemets, vous devrez les échapper - 'filename.gsub (/" /, '\\ "')' – gmcnaughton

2

J'ai découvert que mon équipe utilise la pierre précieuse csv_builder, ce qui vous permet d'ajuster le nom du fichier téléchargé en réglant @filename dans le contrôleur. J'attribuerai toujours la bonne réponse à toute personne pouvant expliquer pourquoi j'ai eu le comportement décrit dans OP.

1

Je ne vois pas où vous envoyez ou restituez la sortie ... Est-ce que c'est dans un fichier .csv.erb ou quelque chose? Ou en utilisant csv_builder comme autre réponse? Cela pourrait être l'astuce.

Je suis arrivé avec la même chose en produisant une sortie .xlsx. Une fois que j'avais le fichier sur le disque, je pouvais faire ceci:

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 

dans mon contrôleur, et cela a très bien fonctionné. Peut-être que les en-têtes étaient bousculés par le rendu du modèle.

0

Personnellement, je n'utilise pas render pour ce genre de contenu - je préfère utiliser send_data. Voici un exemple:

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