Spencer K.
Spencer K.

Reputation: 469

Allow users to download a file

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:

Thanks!

Upvotes: 0

Views: 2950

Answers (3)

max
max

Reputation: 101891

There are basically two cases:

1. The file is public and should be downloadable by anyone.

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.

2. The file needs access control

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

Alex Kojin
Alex Kojin

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

user4778326
user4778326

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

Related Questions