Upload ActionDispatch::Http::UploadedFile To Amazon S3 - ruby-on-rails

How can I upload a ActionDispatch::Http::UploadedFile to Amazon S3?
#file_data = params[:upload][:file]
s3 = AWS::S3.new
obj = s3.buckets['WeMake'].objects.create("video", file)
I then get this error: ArgumentError (:data must be provided as a String, Pathname, File, or an object that responds to #read and #eof?):

I needed to access the actual file, params[:upload][:file].tempfile and add a file extension to the s3 upload, obj = s3.buckets['Bucket'].objects.create("video.mov", #file_data.tempfile).

Related

How to verify AWS S3 put response in Rails

I am using aws-skd-s3 gem in my Rails project.
Create S3 resoure
s3 = Aws::S3::Resource.new(access_key_id: #####,
secret_access_key: #####,
region: 'us-east-1')
Create an S3 object
path = 'sample'
key = test.csv
obj = s3.bucket(#{bucket_name}).object("#{path}" + key)
Store CSV in S3
obj.put(body: csv_response, content_type: 'text/csv')
How to verify that put method stored the csv in S3 without any issues?
Is there any status code available for put method in S3 to verify?
Two ways to go about it:
Store the result. It should be a PutObjectOutput type object. You can check out the official method documentation of the put request method.
The second way to go about it is to make a exists? call right after your put request is completed. Something like this:
s3 = Aws::S3::Resource.new(region: 'ap-southeast-1') # change to the region you use
obj = s3.bucket('bucket-name').object("path/to/object/in/bucket")
if obj.exists?
# Object was uploaded successfully!
else
# No it wasn't!
end
Hope that helps!
One way I've seen or read other people doing it is calculating a md5 hash of the original file before upload and then match that with the etag value from the response of obj.put

Uploading files directly to s3

I am trying to upload the file to s3 server, using s3_direct_upload gem. I have followed the instruction in document. But I am unable to upload the file. I am getting following error:
<Code>InvalidRequest</Code>
<Message>The authorization mechanism you have provided is not supported. Please use AWS4-HMAC-SHA256.</Message>
My bucket region is us-east-2.
And following is my initializer content:
S3DirectUpload.config do |c|
c.access_key_id = ENV["AWS_ACCESS_KEY_ID"]
c.secret_access_key = ENV["AWS_SECRET_ACCESS_KEY"]
c.bucket = ENV["AWS_S3_BUCKET"]
c.region = ENV["AWS_REGION"]
c.url = "https://#{ENV['AWS_S3_BUCKET']}.s3.amazonaws.com"
end

How to get file stream in the output of Object.get

I a writing a Rails API, with help of aws-sdk-ruby, which retrieves a file from AWS and returns in the response of API. Can I get somehow file stream in response of object.get, which I can directly return from the Rails API.
s3 = Aws::S3::Resource.new
bucket_name = "my_bucket"
bucket = s3.bucket(bucket_name)
object = bucket.object("a/b/my.pdf")
Rails.logger.info 'Downloading file to AWS'
downloaded_data = object.get({})
send_data(downloaded_data,
:filename => "my.pdf",
:type => "mime/type"
)
But it does not return file.
One option I know is to first save the file in local using this line:
object.get(response_target: '/tmp/my.pdf')
Than I can return this file but is there a way to skip this step and directly return the response of object.get without saving in local.
I can not use this solution as my URL are not public and I am just creating a REST API.
I got screen like following when I tried this solution.
As of now what I am doing is getting a URL from the object like this:
url = object.presigned_url(:get, expires_in: 3600)
and using following code to send the response:
data = open(url)
send_data data.read, filename: file_name, type: "mime/type"

Rails: save file from URL and save it to Amazon S3

What's the more straightforward way to download a file from given URL and uploading it immediately to Amazon S3 (+ save into database some information about the file, like name, size etc)?
Right now, I am not using Paperclip neither Carrierwave.
Thank you
Straightforward:
require 'open-uri'
require 's3'
amazon = S3::Service.new(access_key_id: 'KEY', secret_access_key: 'KEY')
bucket = amazon.buckets.find('image_storage')
url = 'http://www.example.com/url'
download = open(url)
file = bucket.objects.build('image.png')
file.content = (File.read download)
if file.save
# Make a new ActiveRecord::Base class for this
LogFile.create(size: download.size, type: download.type, name: url)
end
https://github.com/qoobaa/s3

Carrierwave and Amazon S3: retrieve image

I have a problem with S3 and CarrierWave:
I have a pseudo-form that uploads data and files, I wrote "pseudo" because it's an ajax form so data is sent with jquery to rails with a POST request. Files cannot be uploaded in this way...so I have a popup windows that upload files to rails, I save in the session the reference to the uploaded files and when the ajax request uploads the rest of the form, I link the files uploaded to the rest of the data.
With storage :file it works without any problems, when i receive the file I do:
uploader = ImgObjUploader.new
uploader.store!(params[:image_form][:image])
session["image"] = uploader.url
and then when I get the rest of the data:
if (session[:image] != nil) then
obj.image = File.open(session[:image])
end
And my model is:
mount_uploader :image, ImgObjUploader
This code work without any problems, for amazon s3 I switched to:
uploader = ImgObjUploader.new
uploader.retrieve_from_store!(session[:image])
puts uploader
#obj.image = uploader
obj.image = uploader.url
but it doesn't work...I didn't receive an error but I don't have the image saved inside obj object. Puts uploader prints the url of amazon S3.
Anyone can help me?
Thank You.

Resources