Jesse Novotny
Jesse Novotny

Reputation: 730

Upload an image to AWS from an image url in Ruby?

I have a source url from an image tag and I want to upload that image to my S3 bucket. How would I do this?

Upvotes: 3

Views: 2745

Answers (2)

Doughtz
Doughtz

Reputation: 359

I know this question is old, but I needed to figure this out and couldn't get the full answer.

Here is how I have done it.

First make sure that it turns into a TempFile. If this is not just some one-time thing and you are doing this in Rails for instance... then you probably want to add this as an initializer or something. Make sure you restart the server so it takes effect.

OpenURI::Buffer.send :remove_const, 'StringMax'
OpenURI::Buffer.const_set 'StringMax', 0

Then you can upload via url

def upload_file(filename, url)
  s3 = Aws::S3::Resource.new(region:'us-west-2')
  obj = s3.bucket(bucket_name).object(filename) # make sure your filename has an extension (.jpg for example)

  File.open(open(url), 'rb') do |file|
    obj.put(body: file)
  end

end

Upvotes: 6

Jesse Novotny
Jesse Novotny

Reputation: 730

A-Ha! I already have the answer but found this quite tricky to figure out...

Unfortunately I was unable to accomplish this task without first downloading the file in question from the source URL.

So here's how I uploaded Product images:

First configure your S3 bucket in app/config/initializers/aws.rb

Aws.config.update({
  region: ENV['AWS_REGION'],
  credentials: Aws::Credentials.new(ENV['AWS_ACCESS_KEY_ID'], ENV['AWS_SECRET_ACCESS_KEY']),
})

S3_BUCKET = Aws::S3::Resource.new.bucket(ENV['S3_BUCKET_NAME'])

Then I created app/workers/aws_importer.rb

require 'aws-sdk'

class AwsImporter  
  def upload_from_url (img_url, product_name)
    image_file = open(img_url) // stage file for saving locally  
    local_image_path = product_name + ".jpg" // define filename and designate to root directory
    IO.copy_stream(image_file, local_image_path) // download file to root directory
    remote_image_path = "/products/#{product_name}/primary_image/#{local_image_path}" // set the desired url path in AWS
    S3_BUCKET.object(remote_image_path).upload_file(local_image_path) // upload file to S3
    File.delete(local_image_path) // then delete the local file copy
    "https://s3.amazonaws.com/#{S3_BUCKET.name}/" + remote_image_path // return the new url path of the uploaded object.
  end
end

Then all you need to do is call:

AwsImporter.new.upload_from_url(img_url, product_name)

This is exactly how I scraped an entire website to seed our database with Products and image_urls that we could control.

Upvotes: 4

Related Questions