3

When send_file is called, it's sending the file to the browser, but the browser is dumping the contents as plain-text on a new page instead of downloading the file. If I refresh that page, it then downloads the file as normal.

Route

get 'download' => 'qr_codes#download'

Controller

def download
    path = Rails.root.join("events/active/#{params[:name]}/#{params[:batch]}/#{params[:file]}")
    send_file(path, type: 'application/vnd.ms-excel', filename: params[:file])
end

View

<%= link_to 'Original Upload', download_path(name: @event_name,
  batch: batch, file: batch_upload_filename(@event_name, batch)) %>

SOLUTION: This ended up being a known issue with turbolinks. If using Turbolinks 5 like I am, the updated syntax is: data: { turbolinks: false }

Matt Weick
  • 332
  • 6
  • 19

3 Answers3

3

This ended up being a known issue with turbolinks. If using Turbolinks 5 like I am, the updated syntax is:

data: { turbolinks: false }
Sergio Tulentsev
  • 226,338
  • 43
  • 373
  • 367
Matt Weick
  • 332
  • 6
  • 19
1

Try setting the disposition:

def download
  path = Rails.root.join("events/active/#{params[:name]}/#{params[:batch]}/#{params[:file]}")
  send_file(path, type: 'application/vnd.ms-excel', filename: params[:file], disposition: 'attachment')
end

Or changing the file to ensure the extension is correct

"#{params[:file][0,params[:file].index(".")]}.xlsx"

Oh and don't inject params into a string to build routes for downloading. I can inject "../../" into :name, "config", into :batch, and "../config/database.yml" into :file. Add the file path to a model.

Andy Gauge
  • 1,428
  • 2
  • 14
  • 25
  • The disposition is defaulted to 'attachment'. I tried setting it anyways and encountered the same result. I also ensured the file extension was correct per your suggestion and got the same result. – Matt Weick Aug 25 '16 at 12:31
  • If I go here directly it downloads fine `"http://localhost:3000/download?batch=1&file=HSS.xls&name=HSS+2016"`, only when I link to this path from a different page does it render the plain-text in the browser, then as I mentioned in post, refreshing the plaintext page, will then download the file as normal. – Matt Weick Aug 25 '16 at 12:47
0

make helper method

def some_helper(content_type)
 Rack::Mime::MIME_TYPES.invert[content_type].gsub(/\./mi, '')
end

and update link as

<%= link_to 'Original Upload', download_path(name: @event_name, batch: batch, file: batch_upload_filename(@event_name, batch, format: file_format(attachment.file.content_type))) %>