2

I'm using Carrierwave to upload my images to S3 which works fine. I would like the user to click a 'Download' link which will auto download the image from S3.

This currently works:

media.html.erb

<%= link_to download_media_partnership_path(@partner, m: m.id), target: '_self', data: {disable_with: "<i class='fa fa-spinner fa-spin media-icon'></i>"} 
    <i class="fa fa-download media-icon download" id=""></i>
<% end %>

partnership_controller.rb

def download_media
  @media = TeamMedia.find(params[:m])
  file_data = open(@media.attachment.url)
  send_data file_data.read, filename: "#{@media.name}", type: @media.attachment.content_type, disposition: 'attachment'
end

team_media.rb

mount_uploader :attachment, TeamMediaUploader

The problem is that open(@media.attachment.url) causes the the app to download the file first before sending to the user. The user will be downloading videos so it takes ages before they get the 'download' popup.

Any way I can edit the above to work like this answer so my app doesn't have to download first? I can't get it to work with Carrierwave credentials. Or an alternative solution.

MikeHolford
  • 1,851
  • 2
  • 21
  • 32
  • You want to let download via browser ? – 7urkm3n Feb 17 '18 at 02:01
  • Possible duplicate of [Using send\_file to download a file from Amazon S3?](https://stackoverflow.com/questions/12277971/using-send-file-to-download-a-file-from-amazon-s3) – ErvalhouS Feb 17 '18 at 02:02
  • @ErvalhouS You will notice it's slightly different. I did reference that question in a link in my question. I need to be able to do it qith Carrierwave – MikeHolford Feb 17 '18 at 02:05
  • @7urkm3n Yes without having to download the media myself from S3 – MikeHolford Feb 17 '18 at 02:05

2 Answers2

2

I can suggest you use JavaScript to download a data(file/image) anything.

You can do ajax call to server to get an url.

#removed: target: '_self' no need it anymore
#added: remote: true
<%= link_to download_media_partnership_path(@partner, m: m.id), remote: true, data: {disable_with: "<i class='fa fa-spinner fa-spin media-icon'></i>"} 
    <i class="fa fa-download media-icon download" id=""></i>
<% end %>


def download_media
  @media = TeamMedia.find(params[:m])
  @url = @media.attachment.url

  respond_to do |format|
    format.js {}
  end
end

Check this Link and implement into your javascript assets.

Do not forget to create download_media.js.erb file.

#download_media.js.erb

downloadFile("<%= @url %>");
7urkm3n
  • 6,054
  • 4
  • 29
  • 46
  • This doesn''t seem to actually download it. It just renders a new tab with the URL set as `@url`. It's works the same as me writing `link_to @media.attachment.url` – MikeHolford Feb 17 '18 at 02:35
  • @MikeHolford did u check the link ? also, u dnt have to get new tab. – 7urkm3n Feb 17 '18 at 02:39
  • Works well actually. Nice experience with Remote:true and it causes my disable_with to re-enable. thanks – MikeHolford Feb 17 '18 at 02:51
  • @MikeHolford glad that helped, also dnt forget to remove other post about `disable_with to re-enable` – 7urkm3n Feb 17 '18 at 04:08
0

I would just link to the source file directly on S3, instead of proxying through my Rails app at all.

<%= link_to @partner.media.url, "Download" %>

The Carrierwave url method should return the URL to retrieve the object on the remote store, and link_to doesn't just take routes, but also strings - in this case strings to another URL.

If you want to force the user to download, not just render the file, you could use the HTML5 download attribute (in which case I might even abandon using the link_to helper at all, just building the HTML link code by hand??).

RyanWilcox
  • 13,890
  • 1
  • 36
  • 60