nulogy-s3_direct_upload 0.0.5.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.
@@ -0,0 +1,227 @@
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
+ Add this line to your application's Gemfile:
10
+
11
+ gem 's3_direct_upload'
12
+
13
+ Then add a new initalizer with your AWS credentials:
14
+
15
+ **config/initalizers/s3_direct_upload.rb**
16
+ ```ruby
17
+ S3DirectUpload.config do |c|
18
+ c.access_key_id = "" # your access key id
19
+ c.secret_access_key = "" # your secret access key
20
+ c.bucket = "" # your bucket name
21
+ end
22
+ ```
23
+
24
+ Make sure your AWS S3 CORS settings for your bucket look something like this:
25
+ ```xml
26
+ <CORSConfiguration>
27
+ <CORSRule>
28
+ <AllowedOrigin>http://0.0.0.0:3000</AllowedOrigin>
29
+ <AllowedMethod>GET</AllowedMethod>
30
+ <AllowedMethod>POST</AllowedMethod>
31
+ <AllowedMethod>PUT</AllowedMethod>
32
+ <MaxAgeSeconds>3000</MaxAgeSeconds>
33
+ <AllowedHeader>*</AllowedHeader>
34
+ </CORSRule>
35
+ </CORSConfiguration>
36
+ ```
37
+ In production the AllowedOrigin key should be your domain.
38
+
39
+ Add the following js and css to your asset pipeline:
40
+
41
+ **application.js.coffee**
42
+ ```coffeescript
43
+ #= require s3_direct_upload
44
+ ```
45
+
46
+ **application.css**
47
+ ```css
48
+ //= require s3_direct_upload_progress_bars
49
+ ```
50
+
51
+ ## Usage
52
+ Create a new view that uses the form helper `s3_uploader_form`:
53
+ ```ruby
54
+ <%= s3_uploader_form post: model_url, as: "model[image_url]", id: "myS3Uploader" do %>
55
+ <%= file_field_tag :file, multiple: true %>
56
+ <% end %>
57
+ ```
58
+
59
+ Then in your application.js.coffee, call the S3Uploader jQuery plugin on the element you created above:
60
+ ```coffeescript
61
+ jQuery ->
62
+ $("#myS3Uploader").S3Uploader()
63
+ ```
64
+
65
+ Optionally, you can also place this template in the same view for the progress bars:
66
+ ```js+erb
67
+ <script id="template-upload" type="text/x-tmpl">
68
+ <div class="upload">
69
+ {%=o.name%}
70
+ <div class="progress"><div class="bar" style="width: 0%"></div></div>
71
+ </div>
72
+ </script>
73
+ ```
74
+
75
+ ## Options for form helper
76
+ * `post:` url in which is POST'd to after file is uploaded to S3. If you don't specify this option, no callback to the server will be made after the file has uploaded to S3.
77
+ * `as:` parameter value for the POST in which the key will be the URL of the file on S3. If for example this is set to "model[image_url]" then the data posted would be `model[image_url] : http://bucketname.s3.amazonws.com/filename.ext`
78
+ * `key:` key on s3. defaults to `"uploads/#{SecureRandom.hex}/${filename}"`. needs to be at least `"${filename}"`.
79
+ * `acl:` acl for files uploaded to s3, defaults to "public-read"
80
+ * `max_file_size:` maximum file size, defaults to 500.megabytes
81
+ * `id:` html id for the form, its recommended that you give the form an id so you can reference with the jQuery plugin.
82
+ * `class:` optional html class for the form.
83
+ * `data:` Optional html data
84
+
85
+ ### Persisting the S3 url
86
+ It is recommended that you persist the image_url that is sent back from the POST request (to the url given to the `post` option and as the key given in the `as` option). So to access your files later.
87
+
88
+ One way to do this is to make sure you have `resources model` in your routes file, and add the `image_url` (or whatever you would like to name it) attribute to your model, and then make sure you have the create action in your controller for that model.
89
+
90
+ You could then have your create action render a javascript file like this:
91
+ **create.js.erb**
92
+ ```ruby
93
+ <% if @model.new_record? %>
94
+ alert("Failed to upload model: <%= j @model.errors.full_messages.join(', ').html_safe %>");
95
+ <% else %>
96
+ $("#container").append("<%= j render(@model) %>");
97
+ <% end %>
98
+ ```
99
+ So that javascript code would be executed after the model instance is created, without a page refresh. See [@rbates's gallery-jquery-fileupload](https://github.com/railscasts/383-uploading-to-amazon-s3/tree/master/gallery-jquery-fileupload)) for an example of that method.
100
+
101
+ Note: the POST request to the rails app also includes the following parameters `filesize`, `filetype`, `filename` and `filepath`.
102
+
103
+ ### Advanced Customizations
104
+ Feel free to override the styling for the progress bars in s3_direct_upload_progress_bars.css, look at the source for inspiration.
105
+
106
+ 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.
107
+ To do this remove `s3_direct_upload` from your application.js and include the necessary jquery-file-upload scripts in your asset pipeline (they are included in this gem automatically):
108
+ ```cofeescript
109
+ #= require jquery-fileupload/basic
110
+ #= require jquery-fileupload/vendor/tmpl
111
+ ```
112
+ Use the javascript in `s3_direct_upload` as a guide.
113
+
114
+
115
+ ## Options for S3Upload jQuery Plugin
116
+
117
+ * `path:` manual path for the files on your s3 bucket. Example: `path/to/my/files/on/s3`
118
+ Note: the file path in your s3 bucket will effectively be `path + key`.
119
+ * `additional_data:` You can send additional data to your rails app in the persistence POST request. This would be accessable in your params hash as `params[:key][:value]`
120
+ Example: `{key: value}`
121
+ * `remove_completed_progress_bar:` By default, the progress bar will be removed once the file has been successfully uploaded. You can set this to `false` if you want to keep the progress bar.
122
+ * `before_add:` Callback function that executes before a file is added to the queue. It is passed file object and expects `true` or `false` to be returned. This could be useful if you would like to validate the filenames of files to be uploaded for example. If true is returned file will be uploaded as normal, false will cancel the upload.
123
+
124
+ ### Example with all options.
125
+ ```coffeescript
126
+ jQuery ->
127
+ $("#myS3Uploader").S3Uploader
128
+ path: 'path/to/my/files/on/s3'
129
+ additional_data: {key: 'value'}
130
+ remove_completed_progress_bar: false
131
+ before_add: myCallBackFunction() # must return true or false if set
132
+ ```
133
+
134
+ ### Public methods
135
+ You can change the settings on your form later on by accessing the jQuery instance:
136
+
137
+ ```coffeescript
138
+ jQuery ->
139
+ v = $("#myS3Uploader").S3Uploader()
140
+ ...
141
+ v.path("new/path/")
142
+ v.additional_data("newdata")
143
+ ```
144
+
145
+ ### Javascript Events Hooks
146
+
147
+ #### First upload started
148
+ `s3_uploads_start` is fired once when any batch of uploads is starting.
149
+ ```coffeescript
150
+ $('#myS3Uploader').bind 's3_uploads_start', (e) ->
151
+ alert("Uploads have started")
152
+ ```
153
+
154
+ #### Successfull upload
155
+ When a file has been successfully to S3, the `s3_upload_complete` is triggered on the form. A `content` object is passed along with the following attributes :
156
+
157
+ * `url` The full URL to the uploaded file on S3.
158
+ * `filename` The original name of the uploaded file.
159
+ * `filepath` The path to the file (without the filename or domain)
160
+ * `filesize` The size of the uploaded file.
161
+ * `filetype` The type of the uploaded file.
162
+
163
+ This hook could be used for example to fill a form hidden field with the returned S3 url :
164
+ ```coffeescript
165
+ $('#myS3Uploader').bind "s3_upload_complete", (e, content) ->
166
+ $('#someHiddenField').val(content.url)
167
+ ```
168
+
169
+ #### Failed upload
170
+ When an error occured during the transferm the `s3_upload_failed` is triggered on the form with the same `content` object is passed for the successful upload with the addition of the `error_thrown` attribute. The most basic way to handle this error would be to display an alert message to the user in case the upload fails :
171
+ ```coffeescript
172
+ $('#myS3Uploader').bind "s3_upload_failed", (e, content) ->
173
+ alert("#{content.filename} failed to upload : #{content.error_thrown}")
174
+ ```
175
+
176
+ #### All uploads completed
177
+ When all uploads finish in a batch an `s3_uploads_complete` event will be triggered on `document`, so you could do something like:
178
+ ```coffeescript
179
+ $(document).bind 's3_uploads_complete', ->
180
+ alert("All Uploads completed")
181
+ ```
182
+
183
+ ## Cleaning old uploads on S3
184
+ You may be processing the files upon upload and reuploading them to another
185
+ bucket or directory. If so you can remove the originali files by running a
186
+ rake task.
187
+
188
+ First, add the fog gem to your `Gemfile` and run `bundle`:
189
+ ```ruby
190
+ require 'fog'
191
+ ```
192
+
193
+ Then, run the rake task to delete uploads older than 2 days:
194
+ ```
195
+ $ rake s3_direct_upload:clean_remote_uploads
196
+ Deleted file with key: "uploads/20121210T2139Z_03846cb0329b6a8eba481ec689135701/06 - PCR_RYA014-25.jpg"
197
+ Deleted file with key: "uploads/20121210T2139Z_03846cb0329b6a8eba481ec689135701/05 - PCR_RYA014-24.jpg"
198
+ $
199
+ ```
200
+
201
+ Optionally customize the prefix used for cleaning (default is `uploads/#{2.days.ago.strftime('%Y%m%d')}`):
202
+ **config/initalizers/s3_direct_upload.rb**
203
+ ```ruby
204
+ S3DirectUpload.config do |c|
205
+ # ...
206
+ c.prefix_to_clean = "my_path/#{1.week.ago.strftime('%y%m%d')}"
207
+ end
208
+ ```
209
+
210
+ ## Contributing / TODO
211
+ This is just a simple gem that only really provides some javascript and a form helper.
212
+ This gem could go all sorts of ways based on what people want and how people contribute.
213
+ Ideas:
214
+ * More specs!
215
+ * More options to control file types, ability to batch upload.
216
+ * More convention over configuration on rails side
217
+ * Create generators.
218
+ * Model methods.
219
+ * Model method to delete files from s3
220
+
221
+
222
+ ## Credit
223
+ 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).
224
+
225
+ Thank you Ryan Bates!
226
+
227
+ 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,104 @@
1
+ #= require jquery-fileupload/basic
2
+ #= require jquery-fileupload/vendor/tmpl
3
+
4
+ $ = jQuery
5
+
6
+ $.fn.S3Uploader = (options) ->
7
+
8
+ # support multiple elements
9
+ if @length > 1
10
+ @each ->
11
+ $(this).S3Uploader options
12
+
13
+ return this
14
+
15
+ $uploadForm = this
16
+
17
+ settings =
18
+ path: ''
19
+ additional_data: null
20
+ before_add: null
21
+ remove_completed_progress_bar: true
22
+
23
+ $.extend settings, options
24
+
25
+ current_files = []
26
+
27
+ setUploadForm = ->
28
+ $uploadForm.fileupload
29
+
30
+ add: (e, data) ->
31
+ current_files.push data
32
+ file = data.files[0]
33
+ unless settings.before_add and not settings.before_add(file)
34
+ data.context = $(tmpl("template-upload", file)) if $('#template-upload').length > 0
35
+ $uploadForm.append(data.context)
36
+ data.submit()
37
+
38
+ start: (e) ->
39
+ $uploadForm.trigger("s3_uploads_start", [e])
40
+
41
+ progress: (e, data) ->
42
+ if data.context
43
+ progress = parseInt(data.loaded / data.total * 100, 10)
44
+ data.context.find('.bar').css('width', progress + '%')
45
+
46
+ done: (e, data) ->
47
+ content = build_content_object $uploadForm, data.files[0], data.result
48
+
49
+ to = $uploadForm.data('post')
50
+ if to
51
+ content[$uploadForm.data('as')] = content.url
52
+ $.post(to, content)
53
+
54
+ data.context.remove() if data.context && settings.remove_completed_progress_bar # remove progress bar
55
+ $uploadForm.trigger("s3_upload_complete", [content])
56
+
57
+ current_files.splice($.inArray(data, current_files), 1) # remove that element from the array
58
+ $uploadForm.trigger("s3_uploads_complete", [content]) unless current_files.length
59
+
60
+ fail: (e, data) ->
61
+ content = build_content_object $uploadForm, data.files[0], data.result
62
+ content.error_thrown = data.errorThrown
63
+ $uploadForm.trigger("s3_upload_failed", [content])
64
+
65
+ formData: (form) ->
66
+ data = form.serializeArray()
67
+ fileType = ""
68
+ if "type" of @files[0]
69
+ fileType = @files[0].type
70
+ data.push
71
+ name: "Content-Type"
72
+ value: fileType
73
+
74
+ data[1].value = settings.path + data[1].value #the key
75
+ data
76
+
77
+ build_content_object = ($uploadForm, file, result) ->
78
+ content = {}
79
+ if result # Use the S3 response to set the URL to avoid character encodings bugs
80
+ content.url = $(result).find("Location").text()
81
+ content.filepath = $('<a />').attr('href', content.url)[0].pathname
82
+ else # IE <= 9 return a null result object so we use the file object instead
83
+ domain = $uploadForm.attr('action')
84
+ content.filepath = settings.path + $uploadForm.find('input[name=key]').val().replace('/${filename}', '')
85
+ content.url = domain + content.filepath + '/' + encodeURIComponent(file.name)
86
+
87
+ content.filename = file.name
88
+ content.filesize = file.size if 'size' of file
89
+ content.filetype = file.type if 'type' of file
90
+ content = $.extend content, settings.additional_data if settings.additional_data
91
+ content
92
+
93
+ #public methods
94
+ @initialize = ->
95
+ setUploadForm()
96
+ this
97
+
98
+ @path = (new_path) ->
99
+ settings.path = new_path
100
+
101
+ @additional_data = (new_data) ->
102
+ settings.additional_data = new_data
103
+
104
+ @initialize()
@@ -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,13 @@
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
+ require 's3_direct_upload/railtie' if defined?(Rails)
12
+
13
+ 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, :prefix_to_clean]
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,90 @@
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
+ aws_access_key_id: S3DirectUpload.config.access_key_id,
16
+ aws_secret_access_key: S3DirectUpload.config.secret_access_key,
17
+ bucket: S3DirectUpload.config.bucket,
18
+ acl: "public-read",
19
+ expiration: 10.hours.from_now.utc.iso8601,
20
+ max_file_size: 500.megabytes,
21
+ as: "file",
22
+ key: key
23
+ )
24
+ end
25
+
26
+ def form_options
27
+ {
28
+ id: @options[:id],
29
+ class: @options[:class],
30
+ method: "post",
31
+ authenticity_token: false,
32
+ multipart: true,
33
+ data: {
34
+ post: @options[:post],
35
+ as: @options[:as]
36
+ }.reverse_merge(@options[:data] || {})
37
+ }
38
+ end
39
+
40
+ def fields
41
+ {
42
+ :key => @options[:key] || key,
43
+ :acl => @options[:acl],
44
+ "AWSAccessKeyId" => @options[:aws_access_key_id],
45
+ :policy => policy,
46
+ :signature => signature,
47
+ :success_action_status => "201",
48
+ 'X-Requested-With' => 'xhr'
49
+ }
50
+ end
51
+
52
+ def key
53
+ @key ||= "uploads/#{DateTime.now.utc.strftime("%Y%m%dT%H%MZ")}_#{SecureRandom.hex}/${filename}"
54
+ end
55
+
56
+ def url
57
+ "https://s3.amazonaws.com/#{@options[:bucket]}/"
58
+ end
59
+
60
+ def policy
61
+ Base64.encode64(policy_data.to_json).gsub("\n", "")
62
+ end
63
+
64
+ def policy_data
65
+ {
66
+ expiration: @options[:expiration],
67
+ conditions: [
68
+ ["starts-with", "$utf8", ""],
69
+ ["starts-with", "$key", ""],
70
+ ["starts-with", "$x-requested-with", ""],
71
+ ["content-length-range", 0, @options[:max_file_size]],
72
+ ["starts-with","$Content-Type",""],
73
+ {bucket: @options[:bucket]},
74
+ {acl: @options[:acl]},
75
+ {success_action_status: "201"}
76
+ ]
77
+ }
78
+ end
79
+
80
+ def signature
81
+ Base64.encode64(
82
+ OpenSSL::HMAC.digest(
83
+ OpenSSL::Digest::Digest.new('sha1'),
84
+ @options[:aws_secret_access_key], policy
85
+ )
86
+ ).gsub("\n", "")
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,7 @@
1
+ module S3DirectUpload
2
+ class Railtie < Rails::Railtie
3
+ initializer "railtie.configure_rails_initialization" do |app|
4
+ app.middleware.use JQuery::FileUpload::Rails::Middleware
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,3 @@
1
+ module S3DirectUpload
2
+ VERSION = "0.0.5.1"
3
+ end
@@ -0,0 +1,57 @@
1
+ namespace :s3_direct_upload do
2
+ desc "Removes old uploads from specified s3 bucket/directory -- Useful when uploads are processed into another directory"
3
+ task :clean_remote_uploads do
4
+ require 'thread'
5
+ require 'fog'
6
+
7
+ s3 = Fog::Storage::AWS.new(aws_access_key_id: S3DirectUpload.config.access_key_id, aws_secret_access_key: S3DirectUpload.config.secret_access_key)
8
+ bucket = S3DirectUpload.config.bucket
9
+ prefix = S3DirectUpload.config.prefix_to_clean || "uploads/#{2.days.ago.strftime('%Y%m%d')}"
10
+
11
+ queue = Queue.new
12
+ semaphore = Mutex.new
13
+ threads = []
14
+ thread_count = 20
15
+ total_listed = 0
16
+ total_deleted = 0
17
+
18
+ threads << Thread.new do
19
+ Thread.current[:name] = "get files"
20
+ # Get all the files from this bucket. Fog handles pagination internally.
21
+ s3.directories.get("#{bucket}").files.all({prefix: prefix}).each do |file|
22
+ queue.enq(file)
23
+ total_listed += 1
24
+ end
25
+ # Add a final EOF message to signal the deletion threads to stop.
26
+ thread_count.times { queue.enq(:EOF) }
27
+ end
28
+
29
+ # Delete all the files in the queue until EOF with N threads.
30
+ thread_count.times do |count|
31
+ threads << Thread.new(count) do |number|
32
+ Thread.current[:name] = "delete files(#{number})"
33
+ # Dequeue until EOF.
34
+ file = nil
35
+ while file != :EOF
36
+ # Dequeue the latest file and delete it. (Will block until it gets a new file.)
37
+ file = queue.deq
38
+ unless file == :EOF
39
+ file.destroy
40
+ puts %Q{Deleted file with key: "#{file.key}"}
41
+ end
42
+ # Increment the global synchronized counter.
43
+ semaphore.synchronize {total_deleted += 1}
44
+ end
45
+ end
46
+ end
47
+
48
+ # Wait for the threads to finish.
49
+ threads.each do |t|
50
+ begin
51
+ t.join
52
+ rescue RuntimeError => e
53
+ puts "Failure on thread #{t[:name]}: #{e.message}"
54
+ end
55
+ end
56
+ end
57
+ end
metadata ADDED
@@ -0,0 +1,123 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: nulogy-s3_direct_upload
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.5.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Wayne Hoover
9
+ - Dan Teoh
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2012-12-28 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rails
17
+ requirement: !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ~>
21
+ - !ruby/object:Gem::Version
22
+ version: '3.2'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ~>
29
+ - !ruby/object:Gem::Version
30
+ version: '3.2'
31
+ - !ruby/object:Gem::Dependency
32
+ name: coffee-rails
33
+ requirement: !ruby/object:Gem::Requirement
34
+ none: false
35
+ requirements:
36
+ - - ~>
37
+ - !ruby/object:Gem::Version
38
+ version: 3.2.1
39
+ type: :runtime
40
+ prerelease: false
41
+ version_requirements: !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ~>
45
+ - !ruby/object:Gem::Version
46
+ version: 3.2.1
47
+ - !ruby/object:Gem::Dependency
48
+ name: sass-rails
49
+ requirement: !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 3.2.5
55
+ type: :runtime
56
+ prerelease: false
57
+ version_requirements: !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ~>
61
+ - !ruby/object:Gem::Version
62
+ version: 3.2.5
63
+ - !ruby/object:Gem::Dependency
64
+ name: jquery-fileupload-rails
65
+ requirement: !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ~>
69
+ - !ruby/object:Gem::Version
70
+ version: 0.4.0
71
+ type: :runtime
72
+ prerelease: false
73
+ version_requirements: !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ~>
77
+ - !ruby/object:Gem::Version
78
+ version: 0.4.0
79
+ description: Direct Upload to Amazon S3 With CORS and jquery-file-upload
80
+ email:
81
+ - w@waynehoover.com
82
+ - engineering@nulogy.com
83
+ executables: []
84
+ extensions: []
85
+ extra_rdoc_files: []
86
+ files:
87
+ - lib/s3_direct_upload/engine.rb
88
+ - lib/s3_direct_upload/form_helper.rb
89
+ - lib/s3_direct_upload/config_aws.rb
90
+ - lib/s3_direct_upload/version.rb
91
+ - lib/s3_direct_upload/railtie.rb
92
+ - lib/tasks/s3_direct_upload.rake
93
+ - lib/s3_direct_upload.rb
94
+ - app/assets/stylesheets/s3_direct_upload_progress_bars.css.scss
95
+ - app/assets/javascripts/s3_direct_upload.js.coffee
96
+ - LICENSE
97
+ - README.md
98
+ homepage: ''
99
+ licenses: []
100
+ post_install_message:
101
+ rdoc_options: []
102
+ require_paths:
103
+ - lib
104
+ required_ruby_version: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ required_rubygems_version: !ruby/object:Gem::Requirement
111
+ none: false
112
+ requirements:
113
+ - - ! '>='
114
+ - !ruby/object:Gem::Version
115
+ version: '0'
116
+ requirements: []
117
+ rubyforge_project:
118
+ rubygems_version: 1.8.24
119
+ signing_key:
120
+ specification_version: 3
121
+ summary: Gives a form helper for Rails which allows direct uploads to s3. Based on
122
+ RailsCast#383
123
+ test_files: []