Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Downloading S3 files(objects) using aws-sdk for ruby in rails

I am not using paperclip or carrierwave or any other gems for interaction with amazon web services s3. In fact, I am not using any models, just directly interacting with S3 objects.

Can someone please provide some code as to how to directly download objects(files) from AWS S3

This is my code so far :

View:

<h2>Download Files</h2>
<%@root_files.each do |file| %>
<% next if @obj %>        
<td>Filename:  <b><%= file %></b></td>
<td><%= link_to "Download", download_url_for(file) %></td>
<% end %>

Corresponding Controller:

def xxx
bucket = AWS::S3.new.buckets[ ENV["BUCKET"]]
@root_files = bucket.as_tree.children.select(&:leaf?).collect(&:key) 
end

download_url_for method:

def download_url_for(file_key)
  s3 = AWS::S3.new
  bucket = s3.buckets[ ENV["BUCKET"]]
  object = bucket.objects[file_key]
  File.open('xxxxx', 'wb') do |file|
    object.read do |chunk|
      file.write(chunk)
    end
  end
end

I need to be able to save the downloaded file on any browsable non-pretedetermined location on my desktop.Id really appreciate view on how to modify the download_url_for method to achieve this.

===================================== I just tried using

<td><%= link_to "Download",object.value.url_for(:read).to_s %></td>

But on downloading I only get a zip file with xml content inside it, not the original file (word document in my case) --- any thoughts on how to modify this so as to get the actual file type and contents? Thanks

=======================Heres my code for uploading the file

View code:

<%= form_tag({:action => 'create_file'}, multipart: true) do %>
<%= file_field_tag 'uploaded_file' %><br />
<%= submit_tag 'Upload' %> <br />
<% end %>

Controller action - create_file action

def create_file 
s3 = AWS::S3.new
bucket = s3.buckets[ENV["BUCKET"]]
key = params[:uploaded_file].original_filename
object = bucket.objects[key] 
object.write(params[:uploaded_file].read)
end

Can someone suggest as to how I can check the MIME type or preserve the filename while uploading if thats the issue as mentioned by @Frederick Cheung? thanks

like image 723
orange88 Avatar asked Nov 02 '22 17:11

orange88


1 Answers

You'd probably be better off providing a url for users to download directly from S3 rather than trying to stream the file through your Rails app.

The aws-sdk provides the url_for method to accomplish this: http://docs.aws.amazon.com/AWSRubySDK/latest/AWS/S3/S3Object.html#url_for-instance_method. It takes a bunch of options for expiration, security, caching, etc. A basic example:

<td><%= link_to "Download", file.url_for(:read) %></td>

--EDIT--

To access the url_for method in the view, you'll need references to the s3 objects. So in your controller, you want to collect objects from the leaf nodes, not keys:

@root_files = bucket.as_tree.children.select(&:leaf?).collect(&:object)
like image 51
rossta Avatar answered Nov 08 '22 09:11

rossta