Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create a rails app that makes file accessible via unique auto-generated links?

I have a file that I would like to make available for online download, but only to selected users.

This is the typical scenario I have in mind

A person who wants the file would typically go to the website and fill out a form to request access to the file.

If I would like to share the file with him/her, I would authorize the user which should generate a unique link that would be sent to the user via email. The link would be valid only for certain time period.

I would be using rails for this. The things that I am looking answers for:

  1. What is the right way to generate the unique link for download?
  2. How do I start the download of the file when the user clicks on the link within the valid time frame?
like image 745
Ankit Avatar asked Dec 13 '12 18:12

Ankit


1 Answers

First you'll want to setup a model for storing tokens:

rails g model DownloadToken token:string expires_at:timestamp

download_token.rb

class DownloadToken < ActiveRecord::Base  

   attr_accessible :token, :expires_at
   before_create :generate_token

   def generate_token
      self.token = SecureRandom.base64(15).tr('+/=lIO0', 'abc123')
   end

end

Next, setup controller to handle the submitted form (or make changes to an existing action) and generate a token, send email, etc.

class FooController < ApplicationController

  def create
    #process submitted form
    ...
    #create a token that expires in 24 hours
    @token = DownloadToken.create(:expires_at => Time.now + 24.hours)
    #send email and redirect..
  end    
end

You'll want to make sure that your mailer view includes something like:

<%= link_to "Click Me", "/files/downloads?token=#{@token.token}" %>

You'll also want to setup a controller responsible for serving the download and it should look something like this:

class FileController < ApplicationController
  before_filter :check_token

  def check_token
    redirect_to :back, :flash => {:error => "Bad link"} if DownloadToken.where("token = ? and expires_at > ?", params[:token], Time.now).nil?
  end

  def download
    send_file '/home/your_app/downloads/yourfile.zip', :type=>"application/zip", :x_sendfile=>true        
  end

end

routes.rb (assuming Foo is already setup as a RESTful resource)

match 'files/download' => 'files#download'

This code is untested, but it should cover most of what you need and give you an idea of what direction you'll want to take.

Additional reading:

  • SecureRandom
  • x_sendfile
  • ActionMailer basics
like image 94
Noz Avatar answered Sep 28 '22 09:09

Noz