Ruby auf Schienen, wodurch der Benutzer gezwungen wird, eine tmp-Datei herunterzuladen
-
28-10-2019 - |
Frage
Ich habe im tmp-Verzeichnis eine Datei mit dem folgenden Controller-Code erstellt:
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
Dadurch wird die gewünschte Datei im tmp-Verzeichnis erstellt. Ich möchte den Benutzer zwingen, diese Datei herunterzuladen.
Auf meinem lokalen Computer wird die Datei unter folgendem Pfad gespeichert:
/Users/xxxx/Documents/Sites/xxxx/Website/htdocs/tmp/downloads/xxxx.html
Und auf dem Live-Server wird diese URL etwas völlig anderes sein.
Ich habe mich gefragt, wie ich den Benutzer dazu zwingen kann, diese xxxx.html herunterzuladen.
P.S.Wenn ich ein...
redirect_to file_path
...auf dem Controller wird mir nur angezeigt, dass die Route nicht gefunden wurde.
Prost.
Lösung
Werfen Sie einen Blick auf die Datei senden Methode.Es würde ungefähr so aussehen:
send_file Rails.root.join('tmp', 'downloads', 'xxxxx.html'), :type => 'text/html', :disposition => 'attachment'
:disposition => 'attachment' zwingt den Browser, die Datei herunterzuladen, anstatt sie zu rendern.Stellen Sie es auf „inline“, wenn Sie möchten, dass es im Browser geladen wird.Wenn sich Nginx vor Ihrer Rails-App befindet, müssen Sie Ihre Umgebungskonfiguration ändern (d. h.Umgebungen/Produktion.rb):
# For nginx:
config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect'
Andere Tipps
Es ist einfach, Dateipfade mit URLs zu verwechseln, aber es ist eine wichtige Unterscheidung. Was hat einen URL -Weg von /a/b.txt
befindet sich tatsächlich im Systempfad #{Rails.root}/public/a/b.txt
Möglicherweise müssen Sie dies möglicherweise angehen, indem Sie beide zusammengenehmigt werden.
So können Sie das ansprechen:
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
Sie können nicht zu einer Ressource umgeleitet, die nicht über Ihren Webserver ausgesetzt ist, und im Allgemeinen nur Dinge in public/
sind auf diese Weise eingestellt. Sie können zusätzliche Pfade einfügen, wenn Sie Ihren Server entsprechend konfigurieren.
Sie können diesen gesamten Prozess auch auf der Seite streichen, indem Sie die Antwort einfach als herunterladbarer Inline-Anhang rendern, falls Sie es vorziehen:
render(:action => :show, :layout => nil, :content_type=> 'application/octet-stream')