Skip to content

Instantly share code, notes, and snippets.

@dux
Last active September 14, 2016 09:29
Show Gist options
  • Save dux/bccf681cf7ff0ae9fa10fb9669db3e56 to your computer and use it in GitHub Desktop.
Save dux/bccf681cf7ff0ae9fa10fb9669db3e56 to your computer and use it in GitHub Desktop.
AWS S3 local file or URL upload
require 'aws-sdk'
require 'json'
require 'digest'
['AWS_REGION', 'AWS_ACCESS_KEY_ID', 'AWS_SECRET_ACCESS_KEY'].each { |key|
next if ENV[key]
puts "ENV key '#{key}' not defined (AwsS3)"
exit
}
Aws.config.update({
region: ENV['AWS_REGION'],
credentials: Aws::Credentials.new(ENV['AWS_ACCESS_KEY_ID'], ENV['AWS_SECRET_ACCESS_KEY'])
})
module AwsS3
extend self
def list_buckets
s3c = Aws::S3::Client.new
s3c.list_buckets.buckets.map(&:name)
end
# options
# :max_age - defaults to 5 years
# :max_width - resize image to desired max_width before upload
# :bucket
# :is_image - check if downloaded file is image
# upload_file('http://foo.bar/baz.jpeg', max_width:800)
def upload_file(source, opts={})
opts[:is_image] = true if opts[:max_width]
opts[:bucket] ||= ENV['AWS_BUCKET']
raise "no bucket defined and no ENV['AWS_BUCKET'] set" unless opts[:bucket]
ext = source.split('.').last || 'jpeg'
ext = 'jpeg' if ext == 'jpg' || ext.length != 3
file_name = source.split('/').last.split('?').first.gsub(/[^\w\-\.](\.\w+)/,'')
file_name.gsub!(/%../,'')
file_name.gsub!(/[^\w\-\.]/,'')
file_name = "#{Digest::MD5.hexdigest(source)}-#{file_name}.#{ext}".downcase
local_file = "./tmp/tmp-#{file_name}"
File.unlink(local_file) if File.exists?(local_file)
if source =~ /^http/
# find local file name and unlink if present
source = source.gsub(' ','%20')
# download image
system "curl -o '#{local_file}' '#{source}' "
else
raise "File #{source} not found" unless File.exists?(source)
`cp '#{cource}}' '#{local_file}'`
end
raise 'Local file not found' unless File.exists? local_file
# resize image if needed
`convert '#{local_file}' -resize '#{opts[:max_width]}x3000>' '#{local_file}'` if opts[:max_width]
if opts[:is_image]
dimensions = `identify #{local_file}`.split(' ')[2].to_s.split('x').map(&:to_i)
raise "Not an image" unless dimensions[0] > 10 && dimensions[1] > 10
end
remote_file = "#{Time.now.strftime('%Y/%m/%d/%H')}/#{file_name}"
s3r = Aws::S3::Resource.new
meta = {}
meta['Content-Type'] = "image/#{ext}"
meta['ETag'] = Digest::MD5.hexdigest File.read local_file
meta['Cache-Control'] = "max-age=#{opts[:max_age] || 60*60*24*365*5}"
s3_bucket = s3r.bucket(opts[:bucket])
if s3_bucket.object(remote_file).upload_file(local_file, { metadata: meta, acl: 'public-read' })
remote_file
else
false
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment