Reputation: 469
I've read through a number of StackOverflow threads and tutorials, and I haven't found a good, simple explanation for how to allow a user to download a file from your site.
All I want to do is add a link to one of my views which downloads a file when clicked.
I'd like to understand:
public
?link_to
?routes
? It's just a get
for that controller#action
?Thanks!
Upvotes: 0
Views: 2950
Reputation: 101891
There are basically two cases:
Place it in the /public
directory. Remember that this is the web root - so if you have a file that lives at /public/foo/bar.baz
you would link to the file with <%= link_to 'A file', '/foo/bar.baz' %>
.
No routes or controllers are need since we are just serving a static file from the servers public directory.
In this example we are dynamically servering files stored in /downloads
.
# routes.rb
resources :downloads, only: [:show]
class DownloadsController < ApplicationController
# do your authentication logic here
# GET /downloads/:id
# @example
# GET /downloads/foo.bar would download a file stored at
# /downloads/foo.bar
# @raise [ActiveRecord::RecordNotFound] if the file does not exist.
# This causes a 404 page to be rendered.
def show
fn = Rails.root.join('downloads', params[:id])
raise ActiveRecord::RecordNotFound and return unless file.exists?(fn)
send_file(fn)
end
end
By using Rails to serve the download we can apply whatever access control rules we want.
Upvotes: 2
Reputation: 5204
In simple scenario, you don't need controller to download file. Just save file to public
folder. Public folder is default folder for static resources there are stored compiled js, css, images files, robot.txt and so on.
If you have file monthly-report.doc
. Put it to public/reports/monthly-report.doc
.
In view link_to 'Donwload Report', '/reports/monthly-report.doc'
Upvotes: 2
Reputation:
The link_to
is the same as any other link.
If you want to store it in public then do this in whatever controller action you want.
send_file File.join(Rails.root, 'public', 'file.extension')
You could create a downloads controller and specify that in the index then simply link_to 'Download', download_index_path
or such.
If you're trying to send a file name that a user inputs, you have to sanitize it. If it's "hard coded" like the above example, then you're fine.
Upvotes: 0