5

I would like the user to be able to download a file from a method I set up in a controller. Further, I don’t want the URL to change in my browser when the user downloads the file. I have this link set up

<%= link_to image_tag("cc_icon.png"), scenario_download_cc_path(subscription.scenario), target: '_blank' %>

The problem is, there is a screen blink as a new tab is spawned to generate the download. This looks visually unappealing. I have seen other sites where you click the link and something starts downloading without a blink. How do I do that?

Edit: Here is the function invoked by the link

def download_cc
  scenario = Scenario.find(params[:scenario_id])
  send_data scenario.cc_data, filename: "#{scenario.title}.imscc", type: 'application/zip', :disposition => 'attachment'
end
  • Assuming you're already setting the appropriate content-disposition header on the `scenario_download_cc_path` action, you should be able to simply remove `target: '_blank'` to get the desired behavior. – coreyward Dec 29 '16 at 01:08
  • what does the logic in this action look like: `scenario_download_cc_path(subscription.scenario)`, aka: does it include [send_file](http://apidock.com/rails/ActionController/DataStreaming/send_file)? – BigRon Dec 29 '16 at 01:10
  • @coreyward, per my answer to the guy below, the reason removing "target: '_blank'" is ineffective is because now the URL in my browser changes from "/dashboard" to "/scenarios/27/download_cc" when I click on the link without the "target: '_blank'". –  Dec 29 '16 at 02:36
  • Just make your link as remote. – Darpan Chhatravala Dec 29 '16 at 07:24
  • Ok, how do I do that? –  Dec 29 '16 at 17:51

4 Answers4

2

Just add a "download" attribute to your link:

<%= link_to image_tag("cc_icon.png"), scenario_download_cc_path(subscription.scenario), download: true %>
2

I did some local testing and my hypothesis is that Turbolinks is messing things up. I recommend that you remove target: '_blank' from the link and add data: { turbolinks: false } to opt-out of Turbolinks for this particular link. The code after changes should look like this:

<%= link_to image_tag("cc_icon.png"), scenario_download_cc_path(subscription.scenario), data: { turbolinks: false } %>

Your controller action looks good and needs no changes.

Greg Navis
  • 2,818
  • 10
  • 10
  • Hooray! That solved it . I woudln't have figured that out in a million years. –  Jan 03 '17 at 23:40
0

Remove target

At the moment, you are setting target="_blank", this is telling the browser that when you click the URL, you want to open a new tab. Removing this should just begin the download without opening a tab or window.

< Optional extra info below as I misread your question: >

Formatting the appearance of links

Are you using any HTML or CSS for the design of the site? If so, you can apply css state properties such as "active" "hover" "visited" "link" in your css classes.

Lets say you had a link:

<a href="example.com">My Link</a>

If you created a css file and customised the properties for the link:

a:visited {
    text-decoration: none;
}

that will allow you to alter the appearance of a visited link. You can then use any css property to customise the appearance in any way you want.

Adding CSS files to Ruby app

With Ruby, you can use: <%= stylesheet_link_tag "filename" %> to load in a css file.

Sources: http://www.w3schools.com/css/css_link.asp How do I use CSS with a ruby on rails application?

Community
  • 1
  • 1
MishMash95
  • 753
  • 7
  • 9
  • I was under the impression that the blink was caused by the tab opening, download happening and closing again as there is no content on the tab, though I may have mis-understood. A "screen blink" shouldn't occur in any browser or application, unless there is any weird CSS going on. – MishMash95 Dec 29 '16 at 01:31
  • The reason this doesn't work is because you've violated one of the items in my question -- I don't want the URL in the browser bar to change. Using your solution, the URL changes from "/dashboard" to "/scenarios/27/download_cc". You are correct about summarizing what I emant by "blinking," though. –  Dec 29 '16 at 02:35
  • Hmm, It shouldn't do that as you have content disposition set to attachment. The only thing I can think of is that there is a syntax error in your command. There is a slight inconsistency with your parameters, you have the colon after in: " :disposition =>", but have it before in type? Could it be ignoring the parameter? – MishMash95 Dec 29 '16 at 02:51
  • The browser may also ignore it being a file attachment link, if the link to the file does not end with a file extension. – MishMash95 Dec 29 '16 at 02:53
  • [your last comment](http://stackoverflow.com/questions/41371840/how-do-i-create-a-download-link-that-doesnt-blink/41372060?noredirect=1#comment69946792_41371950) is a good point I hadn't thought of – BigRon Dec 29 '16 at 03:01
  • The link does end in a file extension. The blink is definitely caused by this "target: _blank" but as I said, removing that causes the URL to change in the browser and that's why I posted the question here. –  Dec 29 '16 at 03:45
0

As long as you use send_file you should not see a screen blink.

The scenario_download_cc_path(subscription.scenario) action in your controller should look like this:

file_path = File.join(Rails.root, "/public/myfile.whatever")
send_file file_path

The behavior on Chrome and IE appears the same whether your link does or does not include target: '_blank'

BigRon
  • 3,182
  • 3
  • 22
  • 47
  • I included the method I use in my question. I wasn't using "send_file" because I only have the data in binary form. Per your solution, do I need to create a file first and then invoke your logic? –  Dec 29 '16 at 02:31
  • I would think that send_data should work, too. Let me think about this for a bit – BigRon Dec 29 '16 at 02:55
  • @Natalia after some research I *do* think that `send_data` is the problem. [send_data](https://github.com/rails/rails/blob/bc4781583d9db237dd928b01743c6db7596a36b3/actionpack/lib/action_controller/metal/data_streaming.rb#L108) actually calls `render`, which will cause the blink. [send_file](https://github.com/rails/rails/blob/bc4781583d9db237dd928b01743c6db7596a36b3/actionpack/lib/action_controller/metal/data_streaming.rb#L66) does not re-`render`. Can you create a Tempfile for your data? – BigRon Dec 29 '16 at 03:15
  • I changed it to send_file but the "blinking" remains. This makes sense because the blinking is not caused by anything on the server, but rather I believe it is being caused by this "target:_blank" thing. Anyway, that's what happened. –  Dec 29 '16 at 03:51