Ruby on rails, ce qui oblige l'utilisateur à télécharger un fichier tmp
-
28-10-2019 - |
Question
J'ai créé un fichier dans le répertoire tmp avec le code du contrôleur suivant:
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
Cela crée le fichier que je voulais dans le répertoire tmp, ce que je veux faire est de forcer l'utilisateur à télécharger ce fichier.
Sur ma machine locale, le fichier est enregistré comme chemin:
/Users/xxxx/Documents/Sites/xxxx/Website/htdocs/tmp/downloads/xxxx.html
Et sur le serveur en direct cette URL sera Somthing totalement différent.
Ce que je me demandais comment puis-je forcer l'utilisateur à télécharger ce xxxx.html?
P.S. Si je mets un ...
redirect_to file_path
... sur le contrôleur juste donner moi une route non trouvé.
Vive.
La solution
Jetez un oeil à la méthode send_file . Il avait l'air quelque chose comme ceci:
send_file Rails.root.join('tmp', 'downloads', 'xxxxx.html'), :type => 'text/html', :disposition => 'attachment'
: Peines => « attachement » forcera le navigateur à télécharger le fichier au lieu de le rendre. Réglez-le sur « inline » si vous voulez charger dans le navigateur. Si nginx est en face de votre application Rails, vous devrez modifier la configuration de votre environnement (environnements / production.rb.):
# For nginx:
config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect'
Autres conseils
Il est facile de chemins de fichiers avec des URL confondez, mais il est une distinction importante. Ce qui a un chemin d'URL de /a/b.txt
est en fait situé dans le chemin du système #{Rails.root}/public/a/b.txt
de sorte que vous devrez peut-être résoudre ce problème en générant à la fois en tandem.
Voici comment vous pouvez répondre à cette question:
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
Vous ne pouvez pas rediriger vers une ressource qui est pas exposé via votre serveur web, et généralement seules choses à public/
sont mis de cette façon. Vous pouvez inclure des chemins supplémentaires si vous configurez votre serveur en conséquence.
Vous pouvez également pas de côté tout ce processus en rendant simplement la réponse en tant que pièce jointe en ligne téléchargeable, si vous préférez:
render(:action => :show, :layout => nil, :content_type=> 'application/octet-stream')