4

I have a folder in my app directory named "uploads" where users can upload files and download files. I don't want the uploads folder to be in the public directory because I want to control download authorization.

In my controller, I have:

send_file Rails.root.join('app', 'uploads', filename), :type => 'application/zip', :disposition => 'inline', :x_sendfile=>true

This actually works fine. The problem is that when I'm on the production server, when I run the rake assets:precompile, and have an assets directory, the file downloads twice. The first time the file downloads, the browser acts as if nothing is going on (no loading spinning), but I see data being transferred in the Google Chrome web developer Network tab. Then after the file has been downloaded, a prompt comes up asking the user if he/she wants to download the file.

Removing the assets folder in the public directory gets rid of this problem, but I want to use the asset pipeline. I also tried changing the asset pipeline requires from require_tree to require_directory.

Does anyone know how to get send_file working properly with the asset pipeline?

Thanks.

Francesco Belladonna
  • 11,361
  • 12
  • 77
  • 147
MichaelHajuddah
  • 547
  • 5
  • 18
  • It looks like it's Turbolinks that is causing this problem. I can see that this function in javascript is being called: `visit = function(url) { if (browserSupportsPushState && browserIsntBuggy) { cacheCurrentPage(); reflectNewUrl(url); return fetchReplacement(url); } else { return document.location.href = url; } };` which causes the file to be downloaded twice. Now the question is... how can I disable turbolinks for one method? – MichaelHajuddah Jul 06 '13 at 22:01
  • For anyone having this problem, I solved it. Pass `'data-no-turbolink' => true` into the link_to helper to stop Turbolinks from messing with the download. – MichaelHajuddah Jul 06 '13 at 22:08

2 Answers2

9

For anyone having this problem, I solved it. Pass

'data-no-turbolink' => true 

into the link_to helper to stop Turbolinks from messing with the download.

https://github.com/rails/turbolinks/issues/182

MichaelHajuddah
  • 547
  • 5
  • 18
0

But if you are using a form with turbooboost = true, instead of link_to, or even with a link_to you can do it like this:

Inside your controller, and inside your action put:

def download
      respond_to do |format|
        format.html do
          data = "Hello World!"
          filename = "Your_filename.docx"
          send_data(data, type: 'application/docx', filename: filename)
        end
        format.js { render js: "window.location.href = '#{controller_download_path(params)}';" }
      end
  end

Replace controller_download_path with a path to your download action,

and place in your routes both post and get for the same path:

post '/download'  => 'your_controller#download',  as: :controller_download
get '/download'  => 'your_controller#download',  as: :controller_download
Aleks
  • 4,866
  • 3
  • 38
  • 69