include gem 's3-directupload-helper', :git => "git://gist.github.com/5202809.git", :require => "s3_directupload_helper" in your Gemfile
S3DirectuploadHelper::Uploader.new({}).fields contains the signature.
Gem::Specification.new do |s| | |
s.name = 's3-directupload-helper' | |
s.version = '0.0.1' | |
s.platform = Gem::Platform::RUBY | |
s.author = 'Raykin' | |
s.email = 'raykincoldxiao@gmail.com' | |
s.summary = 'easy create s3 directupload form in rails' | |
s.description = 'clear and easy' | |
s.files = ['s3_directupload_helper.rb'] | |
s.require_path = '.' | |
end |
module S3DirectuploadHelper | |
class AccessConfig < Struct.new(:access_key_id, :secret_access_key, :bucket, :region) | |
include Singleton | |
end | |
# setup s3 config in config/initializers/an_override_file.rb works | |
def self.access_config | |
if block_given? | |
yield AccessConfig.instance | |
end | |
AccessConfig.instance | |
end | |
def self.access_config_blank? | |
access_config.access_key_id.nil? | |
end | |
# setup s3 config by ENV works too | |
def self.init_access_config | |
access_config do |config| | |
config.access_key_id = ENV['s3_access_key_id'] || ENV['S3_ACCESS_KEY_ID'] | |
config.secret_access_key = ENV['s3_secret_access_key'] || ENV['S3_SECRET_ACCESS_KEY'] | |
config.bucket = ENV['s3_bucket'] || ENV['S3_BUCKET'] | |
end | |
end | |
class Uploader | |
def initialize(options) | |
S3DirectuploadHelper.init_access_config if S3DirectuploadHelper.access_config_blank? | |
@options = options.reverse_merge( | |
aws_access_key_id: S3DirectuploadHelper.access_config.access_key_id, | |
aws_secret_access_key: S3DirectuploadHelper.access_config.secret_access_key, | |
bucket: S3DirectuploadHelper.access_config.bucket, | |
region: S3DirectuploadHelper.access_config.region || "s3", | |
acl: "public-read", | |
expiration: 10.hours.from_now.utc.iso8601, | |
max_file_size: 500.megabytes, | |
as: "file", | |
key: default_key | |
) | |
end | |
def form_options | |
{ | |
id: @options[:id], | |
class: @options[:class], | |
method: "post", | |
authenticity_token: false, | |
multipart: true, | |
data: { | |
post: @options[:post], | |
as: @options[:as] | |
}.reverse_merge(@options[:data] || {}) | |
} | |
end | |
def fields | |
{ | |
:key => @options[:key] || default_key, | |
:acl => @options[:acl], | |
"AWSAccessKeyId" => @options[:aws_access_key_id], | |
:policy => policy, | |
:signature => signature, | |
:success_action_status => "201", | |
'X-Requested-With' => 'xhr', | |
:utf8 => true, | |
'Content-Type' => '' | |
} | |
end | |
def default_key | |
@key ||= "uploads/#{DateTime.now.utc.strftime("%Y%m%dT%H%MZ")}_#{SecureRandom.hex}/${filename}" | |
end | |
def url | |
"https://#{@options[:region]}.amazonaws.com/#{@options[:bucket]}/" | |
end | |
def policy | |
Base64.encode64(policy_data.to_json).gsub("\n", "") | |
end | |
def policy_data | |
@policy_data ||= { | |
expiration: @options[:expiration], | |
conditions: [ | |
["starts-with", "$utf8", ""], | |
["starts-with", "$key", ""], | |
["starts-with", "$x-requested-with", ""], | |
["content-length-range", 0, @options[:max_file_size]], | |
["starts-with","$Content-Type",""], | |
{bucket: @options[:bucket]}, | |
{acl: @options[:acl]}, | |
{success_action_status: "201"} | |
] | |
} | |
end | |
def add_success_action_redirect(url) | |
policy_data[:conditions] << { success_action_redirect: url } | |
end | |
def signature | |
Base64.encode64( | |
OpenSSL::HMAC.digest( | |
OpenSSL::Digest.new('sha1'), | |
@options[:aws_secret_access_key], policy | |
) | |
).gsub("\n", "") | |
end | |
end | |
end |