Zrobiłem to na stronie, gdzie ludzie płacą za pobieranie pewnych plików, a pliki są przechowywane w RAILS_ROOT/private
. Pierwszą rzeczą, którą musisz wiedzieć, jest to, że chcesz, aby serwer WWW obsługiwał wysyłanie pliku, w przeciwnym razie Twoja aplikacja zostanie wstrzymana, przesyłając duże pliki, a to szybko zatrzyma twoją witrynę, jeśli masz jakiś plik do pobrania. Tak więc, jeśli chcesz sprawdzić autoryzację w kontrolerze, potrzebujesz również sposobu na przejęcie kontroli nad pobieraniem z powrotem na serwer WWW. Najlepszym sposobem na zrobienie tego (o czym wiem) jest nagłówek X-Sendfile obsługiwany przez Nginx, Apache (z modułem) i inne. Po skonfigurowaniu X-Sendfile, gdy twój serwer internetowy otrzyma z aplikacji nagłówek , przejmuje wysyłanie pliku do klienta.
Gdy masz X-Sendfile pracuje na serwerze WWW, prywatny sposób kontroler jak to jest pomocne:
##
# Send a protected file using the web server (via the x-sendfile header).
# Takes the absolute file system path to the file and, optionally, a MIME type.
#
def send_file(filepath, options = {})
options[:content_type] ||= "application/force-download"
response.headers['Content-Type'] = options[:content_type]
response.headers['Content-Disposition'] = "attachment; filename=\"#{File.basename(filepath)}\""
response.headers['X-Sendfile'] = filepath
response.headers['Content-length'] = File.size(filepath)
render :nothing => true
end
Wtedy twoje działania kontroler mógłby wyglądać następująco:
##
# Private file download: check permission first.
#
def download
product = Product.find_by_filename!(params[:filename])
if current_user.has_bought?(product) or current_user.is_superuser?
if File.exist?(path = product.filepath)
send_file path, :content_type => "application/pdf"
else
not_found
end
else
not_authorized
end
end
Oczywiście Twoja metoda autoryzacji będzie się różnić i będziesz musiał zmienić nagłówki, jeśli oferujesz pliki inne niż pliki PDF lub chcesz, aby plik był wyświetlany w przeglądarce (pozbądź się typu zawartości application/force-download
).
Dlaczego nie używa się wbudowanej metody send_file? –
Ponieważ nie wiedziałem o tym! Każdy, kto użyje tej techniki, powinien usunąć moją kaleką definicję metody "send_file", a zamiast tego wywołać Railsowy plik 'send_file path,: type =>" application/pdf ",: x_sendfile => true'. Dzięki za wiadomość, Ryan. –
Skomentowałem dalej "X-Sendfile" pod adresem: http://stackoverflow.com/a/26884350/895245 –