s3_direct_upload 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Wayne
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,123 @@
1
+ # S3DirectUpload
2
+
3
+ Easily generate a form that allows you to upload directly to Amazon S3.
4
+ Multi file uploading supported by jquery-fileupload.
5
+
6
+ Code extracted from Ryan Bates' [gallery-jquery-fileupload](https://github.com/railscasts/383-uploading-to-amazon-s3/tree/master/gallery-jquery-fileupload).
7
+
8
+ ## Installation
9
+
10
+ Add this line to your application's Gemfile:
11
+
12
+ gem 's3_direct_upload'
13
+
14
+ Then add a new initalizer with your AWS credentials:
15
+
16
+ **config/initalizers/s3_direct_upload.rb**
17
+ ```ruby
18
+ S3DirectUpload.config do |c|
19
+ c.access_key_id = "" # your access key id
20
+ c.secret_access_key = "" # your secret access key
21
+ c.bucket = "" # your bucket name
22
+ end
23
+ ```
24
+
25
+ Make sure your AWS S3 CORS settings for your bucket look something like this:
26
+ ```
27
+ <CORSConfiguration>
28
+ <CORSRule>
29
+ <AllowedOrigin>http://0.0.0.0:3000</AllowedOrigin>
30
+ <AllowedMethod>GET</AllowedMethod>
31
+ <AllowedMethod>POST</AllowedMethod>
32
+ <AllowedMethod>PUT</AllowedMethod>
33
+ <MaxAgeSeconds>3000</MaxAgeSeconds>
34
+ <AllowedHeader>*</AllowedHeader>
35
+ </CORSRule>
36
+ </CORSConfiguration>
37
+ ```
38
+ In production the AllowedOrigin key should be your domain.
39
+
40
+ Add the following js and css to your asset pipeline:
41
+
42
+ **application.js**
43
+ ```ruby
44
+ //= require s3_direct_upload
45
+ ```
46
+
47
+ **application.css**
48
+ ```ruby
49
+ //= require s3_direct_upload_progress_bars
50
+ ```
51
+
52
+ ## Usage
53
+
54
+ Create a new view that uses the helper:
55
+ ```ruby
56
+ <%= s3_uploader_form post: model_url, as: "model[image_url]" do %>
57
+ <%= file_field_tag :file, multiple: true %>
58
+ <% end %>
59
+ ```
60
+
61
+ Also place this template in the same view for the progress bars:
62
+ ```javascript
63
+ <script id="template-upload" type="text/x-tmpl">
64
+ <div class="upload">
65
+ {%=o.name%}
66
+ <div class="progress"><div class="bar" style="width: 0%"></div></div>
67
+ </div>
68
+ </script>
69
+ ```
70
+
71
+ ### Customizations
72
+ Feel free to override the styling for the progress bars in s3_direct_upload_progress_bars, look at the source for inspiration.
73
+
74
+ Also feel free to write your own js to interface with jquery-file-upload. You might want to do this to do custom validations on the files before it is sent to S3 for example.
75
+ To do this remove `s3_direct_upload` from your application.js and include the necissary jquery-file-upload scripts (they are included in this gem automatically):
76
+ ```javascript
77
+ //= require jquery-fileupload/basic
78
+ //= require jquery-fileupload/vendor/tmpl
79
+ ```
80
+ and use the `s3_direct_upload` script as a guide, the form helper will still work fine if thats all you need.
81
+
82
+ ### s3_uploader_form options and after upload callback
83
+ After the upload is complete, the script will execute an ajax POST to the model_url given in the `post` option in the form helper.
84
+ The url to the file on S3 will be passed as a key to whatever is in the `as` option.
85
+
86
+ You could have your create action render a javascript file like this:
87
+
88
+ **create.js.erb**
89
+ ```ruby
90
+ <% if @model.new_record? %>
91
+ alert("Failed to upload model: <%= j @model.errors.full_messages.join(', ').html_safe %>");
92
+ <% else %>
93
+ $("#paintings").append("<%= j render(@model) %>");
94
+ <% end %>
95
+ ```
96
+ So that javascript code would be executed after the model instance is created, which would render your _model.html.erb template without a page reload if you wish.
97
+
98
+ It is recommended that you persist the image_url as an attribute on the model. To do this To do this add `resources model` in the routes file, and add the 'image_url' attribute to your model (can be whatever you set it as in the as options)
99
+
100
+
101
+ ## Gotchas
102
+
103
+ Right now you can only have one upload form on a page.
104
+ Upload form is hardcoded with id '#fileupload'
105
+
106
+
107
+ ## Contributing / TODO
108
+
109
+ This is just a simple gem that only really provides some javascript and a form helper.
110
+ This gem could go all sorts of ways based on what people want and how people contribute.
111
+ Ideas:
112
+ More specs!
113
+ More options to control expiration, max filesize, file types etc.
114
+ Create generators.
115
+ Model methods.
116
+
117
+ ## Credit
118
+
119
+ This gem is basically a small wrapper around code that [Ryan Bates](http://github.com/rbates) wrote for [Railscast#383](http://railscasts.com/episodes/383-uploading-to-amazon-s3). Most of the code in this gem was extracted from [gallery-jquery-fileupload](https://github.com/railscasts/383-uploading-to-amazon-s3/tree/master/gallery-jquery-fileupload).
120
+
121
+ Thank you Ryan Bates!
122
+
123
+ This code also uses the excellecnt [jQuery-File-Upload](https://github.com/blueimp/jQuery-File-Upload), which is included in this gem by its rails counterpart [jquery-fileupload-rails](https://github.com/tors/jquery-fileupload-rails)
@@ -0,0 +1,30 @@
1
+ #= require jquery-fileupload/basic
2
+ #= require jquery-fileupload/vendor/tmpl
3
+
4
+ jQuery ->
5
+ $('#fileupload').fileupload
6
+ add: (e, data) ->
7
+ file = data.files[0]
8
+ data.context = $(tmpl("template-upload", file))
9
+ $('#fileupload').append(data.context)
10
+ data.submit()
11
+
12
+ progress: (e, data) ->
13
+ if data.context
14
+ progress = parseInt(data.loaded / data.total * 100, 10)
15
+ data.context.find('.bar').css('width', progress + '%')
16
+
17
+ done: (e, data) ->
18
+ file = data.files[0]
19
+ domain = $('#fileupload').attr('action')
20
+ path = $('#fileupload input[name=key]').val().replace('${filename}', file.name)
21
+ to = $('#fileupload').data('post')
22
+ content = {}
23
+ content[$('#fileupload').data('as')] = domain + path
24
+ $.post(to, content)
25
+ data.context.remove() if data.context # remove progress bar
26
+
27
+ fail: (e, data) ->
28
+ alert("#{data.files[0].name} failed to upload.")
29
+ console.log("Upload failed:")
30
+ console.log(data)
@@ -0,0 +1,17 @@
1
+ .upload {
2
+ border-top: solid 1px #CCC;
3
+ width: 400px;
4
+ padding-top: 10px;
5
+ margin-top: 10px;
6
+
7
+ .progress {
8
+ margin-top: 8px;
9
+ border: solid 1px #555;
10
+ border-radius: 3px;
11
+ -moz-border-radius: 3px;
12
+ .bar {
13
+ height: 10px;
14
+ background: #3EC144;
15
+ }
16
+ }
17
+ }
@@ -0,0 +1,12 @@
1
+ require 's3_direct_upload/version'
2
+ require 'jquery-fileupload-rails' if defined?(Rails)
3
+
4
+ require 'base64'
5
+ require 'openssl'
6
+ require 'digest/sha1'
7
+
8
+ require 's3_direct_upload/config_aws'
9
+ require 's3_direct_upload/form_helper'
10
+ require 's3_direct_upload/engine' if defined?(Rails)
11
+
12
+ ActionView::Base.send(:include, S3DirectUpload::UploadHelper) if defined?(ActionView::Base)
@@ -0,0 +1,18 @@
1
+ require "singleton"
2
+
3
+ module S3DirectUpload
4
+ class Config
5
+ include Singleton
6
+
7
+ ATTRIBUTES = [:access_key_id, :secret_access_key, :bucket]
8
+
9
+ attr_accessor *ATTRIBUTES
10
+ end
11
+
12
+ def self.config
13
+ if block_given?
14
+ yield Config.instance
15
+ end
16
+ Config.instance
17
+ end
18
+ end
@@ -0,0 +1,4 @@
1
+ module S3DirectUpload
2
+ class Engine < ::Rails::Engine
3
+ end
4
+ end
@@ -0,0 +1,84 @@
1
+ module S3DirectUpload
2
+ module UploadHelper
3
+ def s3_uploader_form(options = {}, &block)
4
+ uploader = S3Uploader.new(options)
5
+ form_tag(uploader.url, uploader.form_options) do
6
+ uploader.fields.map do |name, value|
7
+ hidden_field_tag(name, value)
8
+ end.join.html_safe + capture(&block)
9
+ end
10
+ end
11
+
12
+ class S3Uploader
13
+ def initialize(options)
14
+ @options = options.reverse_merge(
15
+ id: "fileupload",
16
+ aws_access_key_id: S3DirectUpload.config.access_key_id,
17
+ aws_secret_access_key: S3DirectUpload.config.secret_access_key,
18
+ bucket: S3DirectUpload.config.bucket,
19
+ acl: "public-read",
20
+ expiration: 10.hours.from_now,
21
+ max_file_size: 500.megabytes,
22
+ as: "file"
23
+ )
24
+ end
25
+
26
+ def form_options
27
+ {
28
+ id: @options[:id],
29
+ method: "post",
30
+ authenticity_token: false,
31
+ multipart: true,
32
+ data: {
33
+ post: @options[:post],
34
+ as: @options[:as]
35
+ }
36
+ }
37
+ end
38
+
39
+ def fields
40
+ {
41
+ :key => key,
42
+ :acl => @options[:acl],
43
+ :policy => policy,
44
+ :signature => signature,
45
+ "AWSAccessKeyId" => @options[:aws_access_key_id],
46
+ }
47
+ end
48
+
49
+ def key
50
+ @key ||= "uploads/#{SecureRandom.hex}/${filename}"
51
+ end
52
+
53
+ def url
54
+ "https://#{@options[:bucket]}.s3.amazonaws.com/"
55
+ end
56
+
57
+ def policy
58
+ Base64.encode64(policy_data.to_json).gsub("\n", "")
59
+ end
60
+
61
+ def policy_data
62
+ {
63
+ expiration: @options[:expiration],
64
+ conditions: [
65
+ ["starts-with", "$utf8", ""],
66
+ ["starts-with", "$key", ""],
67
+ ["content-length-range", 0, @options[:max_file_size]],
68
+ {bucket: @options[:bucket]},
69
+ {acl: @options[:acl]}
70
+ ]
71
+ }
72
+ end
73
+
74
+ def signature
75
+ Base64.encode64(
76
+ OpenSSL::HMAC.digest(
77
+ OpenSSL::Digest::Digest.new('sha1'),
78
+ @options[:aws_secret_access_key], policy
79
+ )
80
+ ).gsub("\n", "")
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,3 @@
1
+ module S3DirectUpload
2
+ VERSION = "0.0.1"
3
+ end
metadata ADDED
@@ -0,0 +1,119 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: s3_direct_upload
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - WayneH
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-09-30 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rails
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '3.2'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '3.2'
30
+ - !ruby/object:Gem::Dependency
31
+ name: coffee-rails
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: 3.2.1
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 3.2.1
46
+ - !ruby/object:Gem::Dependency
47
+ name: sass-rails
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: 3.2.1
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 3.2.1
62
+ - !ruby/object:Gem::Dependency
63
+ name: jquery-fileupload-rails
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: 0.3.4
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: 0.3.4
78
+ description: Direct Upload to Amazon S3 With CORS and jquery-file-upload
79
+ email:
80
+ - wayne@blissofbeing.com
81
+ executables: []
82
+ extensions: []
83
+ extra_rdoc_files: []
84
+ files:
85
+ - lib/s3_direct_upload/config_aws.rb
86
+ - lib/s3_direct_upload/engine.rb
87
+ - lib/s3_direct_upload/form_helper.rb
88
+ - lib/s3_direct_upload/version.rb
89
+ - lib/s3_direct_upload.rb
90
+ - app/assets/javascripts/s3_direct_upload.js.coffee
91
+ - app/assets/stylesheets/s3_direct_upload_progress_bars.css.scss
92
+ - LICENSE
93
+ - README.md
94
+ homepage: ''
95
+ licenses: []
96
+ post_install_message:
97
+ rdoc_options: []
98
+ require_paths:
99
+ - lib
100
+ required_ruby_version: !ruby/object:Gem::Requirement
101
+ none: false
102
+ requirements:
103
+ - - ! '>='
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ required_rubygems_version: !ruby/object:Gem::Requirement
107
+ none: false
108
+ requirements:
109
+ - - ! '>='
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
112
+ requirements: []
113
+ rubyforge_project:
114
+ rubygems_version: 1.8.23
115
+ signing_key:
116
+ specification_version: 3
117
+ summary: Gives a form helper for Rails which allows direct uploads to s3. Based on
118
+ RailsCast#383
119
+ test_files: []