s3_multipart 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +6 -0
- data/.rspec +1 -0
- data/Gemfile +26 -0
- data/Gemfile.lock +177 -0
- data/LICENSE.txt +20 -0
- data/README.md +106 -0
- data/Rakefile +0 -0
- data/app/controllers/s3_multipart/application_controller.rb +4 -0
- data/app/controllers/s3_multipart/uploads_controller.rb +56 -0
- data/app/models/s3_multipart/upload.rb +10 -0
- data/config/routes.rb +3 -0
- data/db/migrate/20110727184726_create_s3_multipart_uploads.rb +12 -0
- data/lib/s3_multipart.rb +55 -0
- data/lib/s3_multipart/action_view_helpers/form_helper.rb +15 -0
- data/lib/s3_multipart/engine.rb +5 -0
- data/lib/s3_multipart/http/net_http.rb +49 -0
- data/lib/s3_multipart/railtie.rb +13 -0
- data/lib/s3_multipart/uploader.rb +85 -0
- data/lib/s3_multipart/uploader/config.rb +15 -0
- data/lib/s3_multipart/version.rb +3 -0
- data/s3_multipart-0.0.1.gem +0 -0
- data/s3_multipart.gemspec +27 -0
- data/spec/integration/uploads_controller_spec.rb +9 -0
- data/spec/internal/app/assets/javascripts/application.js +91 -0
- data/spec/internal/app/assets/javascripts/jquery.js +2 -0
- data/spec/internal/app/assets/javascripts/underscore.js +1 -0
- data/spec/internal/app/assets/stylesheets/application.css +0 -0
- data/spec/internal/app/controllers/application_controller.rb +3 -0
- data/spec/internal/app/controllers/pages_controller.rb +9 -0
- data/spec/internal/app/views/layouts/application.html.erb +17 -0
- data/spec/internal/app/views/pages/upload.html.erb +21 -0
- data/spec/internal/config/database.yml +4 -0
- data/spec/internal/config/routes.rb +4 -0
- data/spec/internal/db/combustion_test.sqlite3 +0 -0
- data/spec/internal/db/schema.rb +14 -0
- data/spec/internal/log/.gitignore +1 -0
- data/spec/internal/public/favicon.ico +0 -0
- data/spec/requests/uploader_spec.rb +48 -0
- data/spec/spec_helper.rb +18 -0
- data/vendor/assets/javascripts/s3_multipart/index.js +1 -0
- data/vendor/assets/javascripts/s3_multipart/s3_multipart.js +478 -0
- metadata +214 -0
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/Gemfile
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
|
4
|
+
|
5
|
+
group :development do
|
6
|
+
gem 'activerecord'
|
7
|
+
gem 'sqlite3'
|
8
|
+
gem 'actionpack' # action_controller, action_view
|
9
|
+
gem 'sprockets'
|
10
|
+
gem "rails"
|
11
|
+
gem "sqlite3"
|
12
|
+
|
13
|
+
# tests
|
14
|
+
gem 'combustion', '~> 0.3.3'
|
15
|
+
gem 'rspec'
|
16
|
+
gem 'rspec-rails'
|
17
|
+
gem 'capybara'
|
18
|
+
|
19
|
+
# assets
|
20
|
+
gem 'sass-rails', '~> 3.2.3'
|
21
|
+
gem 'coffee-rails', '~> 3.2.1'
|
22
|
+
gem 'compass-rails'
|
23
|
+
|
24
|
+
gemspec
|
25
|
+
|
26
|
+
end
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,177 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
s3_multipart (0.0.1)
|
5
|
+
uuid
|
6
|
+
xml-simple
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: https://rubygems.org/
|
10
|
+
specs:
|
11
|
+
actionmailer (3.2.9)
|
12
|
+
actionpack (= 3.2.9)
|
13
|
+
mail (~> 2.4.4)
|
14
|
+
actionpack (3.2.9)
|
15
|
+
activemodel (= 3.2.9)
|
16
|
+
activesupport (= 3.2.9)
|
17
|
+
builder (~> 3.0.0)
|
18
|
+
erubis (~> 2.7.0)
|
19
|
+
journey (~> 1.0.4)
|
20
|
+
rack (~> 1.4.0)
|
21
|
+
rack-cache (~> 1.2)
|
22
|
+
rack-test (~> 0.6.1)
|
23
|
+
sprockets (~> 2.2.1)
|
24
|
+
activemodel (3.2.9)
|
25
|
+
activesupport (= 3.2.9)
|
26
|
+
builder (~> 3.0.0)
|
27
|
+
activerecord (3.2.9)
|
28
|
+
activemodel (= 3.2.9)
|
29
|
+
activesupport (= 3.2.9)
|
30
|
+
arel (~> 3.0.2)
|
31
|
+
tzinfo (~> 0.3.29)
|
32
|
+
activeresource (3.2.9)
|
33
|
+
activemodel (= 3.2.9)
|
34
|
+
activesupport (= 3.2.9)
|
35
|
+
activesupport (3.2.9)
|
36
|
+
i18n (~> 0.6)
|
37
|
+
multi_json (~> 1.0)
|
38
|
+
addressable (2.3.2)
|
39
|
+
arel (3.0.2)
|
40
|
+
builder (3.0.4)
|
41
|
+
capybara (2.0.1)
|
42
|
+
mime-types (>= 1.16)
|
43
|
+
nokogiri (>= 1.3.3)
|
44
|
+
rack (>= 1.0.0)
|
45
|
+
rack-test (>= 0.5.4)
|
46
|
+
selenium-webdriver (~> 2.0)
|
47
|
+
xpath (~> 1.0.0)
|
48
|
+
childprocess (0.3.6)
|
49
|
+
ffi (~> 1.0, >= 1.0.6)
|
50
|
+
chunky_png (1.2.6)
|
51
|
+
coffee-rails (3.2.2)
|
52
|
+
coffee-script (>= 2.2.0)
|
53
|
+
railties (~> 3.2.0)
|
54
|
+
coffee-script (2.2.0)
|
55
|
+
coffee-script-source
|
56
|
+
execjs
|
57
|
+
coffee-script-source (1.4.0)
|
58
|
+
combustion (0.3.3)
|
59
|
+
rails (>= 3.0.0)
|
60
|
+
thor (>= 0.14.6)
|
61
|
+
compass (0.12.2)
|
62
|
+
chunky_png (~> 1.2)
|
63
|
+
fssm (>= 0.2.7)
|
64
|
+
sass (~> 3.1)
|
65
|
+
compass-rails (1.0.3)
|
66
|
+
compass (>= 0.12.2, < 0.14)
|
67
|
+
diff-lcs (1.1.3)
|
68
|
+
erubis (2.7.0)
|
69
|
+
execjs (1.4.0)
|
70
|
+
multi_json (~> 1.0)
|
71
|
+
ffi (1.2.0)
|
72
|
+
fssm (0.2.9)
|
73
|
+
hike (1.2.1)
|
74
|
+
i18n (0.6.1)
|
75
|
+
journey (1.0.4)
|
76
|
+
json (1.7.5)
|
77
|
+
libwebsocket (0.1.7.1)
|
78
|
+
addressable
|
79
|
+
websocket
|
80
|
+
macaddr (1.6.1)
|
81
|
+
systemu (~> 2.5.0)
|
82
|
+
mail (2.4.4)
|
83
|
+
i18n (>= 0.4.0)
|
84
|
+
mime-types (~> 1.16)
|
85
|
+
treetop (~> 1.4.8)
|
86
|
+
mime-types (1.19)
|
87
|
+
multi_json (1.5.0)
|
88
|
+
nokogiri (1.5.6)
|
89
|
+
polyglot (0.3.3)
|
90
|
+
rack (1.4.1)
|
91
|
+
rack-cache (1.2)
|
92
|
+
rack (>= 0.4)
|
93
|
+
rack-ssl (1.3.2)
|
94
|
+
rack
|
95
|
+
rack-test (0.6.2)
|
96
|
+
rack (>= 1.0)
|
97
|
+
rails (3.2.9)
|
98
|
+
actionmailer (= 3.2.9)
|
99
|
+
actionpack (= 3.2.9)
|
100
|
+
activerecord (= 3.2.9)
|
101
|
+
activeresource (= 3.2.9)
|
102
|
+
activesupport (= 3.2.9)
|
103
|
+
bundler (~> 1.0)
|
104
|
+
railties (= 3.2.9)
|
105
|
+
railties (3.2.9)
|
106
|
+
actionpack (= 3.2.9)
|
107
|
+
activesupport (= 3.2.9)
|
108
|
+
rack-ssl (~> 1.3.2)
|
109
|
+
rake (>= 0.8.7)
|
110
|
+
rdoc (~> 3.4)
|
111
|
+
thor (>= 0.14.6, < 2.0)
|
112
|
+
rake (10.0.3)
|
113
|
+
rdoc (3.12)
|
114
|
+
json (~> 1.4)
|
115
|
+
rspec (2.12.0)
|
116
|
+
rspec-core (~> 2.12.0)
|
117
|
+
rspec-expectations (~> 2.12.0)
|
118
|
+
rspec-mocks (~> 2.12.0)
|
119
|
+
rspec-core (2.12.2)
|
120
|
+
rspec-expectations (2.12.1)
|
121
|
+
diff-lcs (~> 1.1.3)
|
122
|
+
rspec-mocks (2.12.1)
|
123
|
+
rspec-rails (2.12.0)
|
124
|
+
actionpack (>= 3.0)
|
125
|
+
activesupport (>= 3.0)
|
126
|
+
railties (>= 3.0)
|
127
|
+
rspec-core (~> 2.12.0)
|
128
|
+
rspec-expectations (~> 2.12.0)
|
129
|
+
rspec-mocks (~> 2.12.0)
|
130
|
+
rubyzip (0.9.9)
|
131
|
+
sass (3.2.3)
|
132
|
+
sass-rails (3.2.5)
|
133
|
+
railties (~> 3.2.0)
|
134
|
+
sass (>= 3.1.10)
|
135
|
+
tilt (~> 1.3)
|
136
|
+
selenium-webdriver (2.27.2)
|
137
|
+
childprocess (>= 0.2.5)
|
138
|
+
libwebsocket (~> 0.1.3)
|
139
|
+
multi_json (~> 1.0)
|
140
|
+
rubyzip
|
141
|
+
sprockets (2.2.2)
|
142
|
+
hike (~> 1.2)
|
143
|
+
multi_json (~> 1.0)
|
144
|
+
rack (~> 1.0)
|
145
|
+
tilt (~> 1.1, != 1.3.0)
|
146
|
+
sqlite3 (1.3.6)
|
147
|
+
systemu (2.5.2)
|
148
|
+
thor (0.16.0)
|
149
|
+
tilt (1.3.3)
|
150
|
+
treetop (1.4.12)
|
151
|
+
polyglot
|
152
|
+
polyglot (>= 0.3.1)
|
153
|
+
tzinfo (0.3.35)
|
154
|
+
uuid (2.3.6)
|
155
|
+
macaddr (~> 1.0)
|
156
|
+
websocket (1.0.6)
|
157
|
+
xml-simple (1.1.2)
|
158
|
+
xpath (1.0.0)
|
159
|
+
nokogiri (~> 1.3)
|
160
|
+
|
161
|
+
PLATFORMS
|
162
|
+
ruby
|
163
|
+
|
164
|
+
DEPENDENCIES
|
165
|
+
actionpack
|
166
|
+
activerecord
|
167
|
+
capybara
|
168
|
+
coffee-rails (~> 3.2.1)
|
169
|
+
combustion (~> 0.3.3)
|
170
|
+
compass-rails
|
171
|
+
rails
|
172
|
+
rspec
|
173
|
+
rspec-rails
|
174
|
+
s3_multipart!
|
175
|
+
sass-rails (~> 3.2.3)
|
176
|
+
sprockets
|
177
|
+
sqlite3
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) Max Gillett
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
# S3 Multipart
|
2
|
+
|
3
|
+
The S3 Multipart gem brings direct multipart uploading to S3 to Rails. Data is piped from the client straight to Amazon S3 and a callback is run when the upload is complete.
|
4
|
+
|
5
|
+
Multipart uploading allows files to be split into many chunks and uploaded in parallel or succession (or both). This can result in dramatically increased upload speeds for the client and allows for the pausing and resuming of uploads. For a more complete overview of multipart uploading as it applies to S3, see the overview [here](http://docs.amazonwebservices.com/AmazonS3/latest/dev/mpuoverview.html).
|
6
|
+
|
7
|
+
## Setup
|
8
|
+
|
9
|
+
Install the gem
|
10
|
+
|
11
|
+
```bash
|
12
|
+
gem install s3_multipart
|
13
|
+
```
|
14
|
+
|
15
|
+
Install the included migrations. This will create a table in your database to track initiated and completed uploads
|
16
|
+
|
17
|
+
```bash
|
18
|
+
rake s3_multipart:install:migrations
|
19
|
+
```
|
20
|
+
|
21
|
+
Add the following to your routes file:
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
mount S3Multipart::Engine => "/s3_multipart"
|
25
|
+
```
|
26
|
+
|
27
|
+
If you are using sprockets, add the following to your application.js file. Make sure that the underscore and jquery libraries have been required before this line.
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
//= require s3_multipart/s3_multipart
|
31
|
+
```
|
32
|
+
|
33
|
+
Also in your application.js file you will need to include the following:
|
34
|
+
|
35
|
+
```javascript
|
36
|
+
$(function() {
|
37
|
+
$(".submit-button").click(function() { // The button class passed into multipart_uploader_form (see "Getting Started")
|
38
|
+
new window.S3MP({
|
39
|
+
bucket: "YOUR_S3_BUCKET"
|
40
|
+
fileSelector: "#uploader", // The input name passed into multipart_uploader_form (see "Getting Started")
|
41
|
+
onComplete: function(num) {
|
42
|
+
console.log("File "+num+" successfully uploaded")
|
43
|
+
},
|
44
|
+
onPause: function(num) {
|
45
|
+
console.log("File "+num+" has been paused")
|
46
|
+
},
|
47
|
+
onCancel: function(num) {
|
48
|
+
console.log("File upload "+num+" was canceled")
|
49
|
+
},
|
50
|
+
onError: function(err) {
|
51
|
+
console.log("There was an error")
|
52
|
+
},
|
53
|
+
onProgress: function(num, size, done, percent, speed) {
|
54
|
+
console.log("File %d is %f percent done (%f of %f total) and uploading at %s", num, percent, done, size, speed);
|
55
|
+
}
|
56
|
+
});
|
57
|
+
});
|
58
|
+
});
|
59
|
+
```
|
60
|
+
|
61
|
+
This piece of code does some configuration and provides various callbacks that you can hook into.
|
62
|
+
|
63
|
+
Finally, create an initializer in config/initializers with the following, adding in your credentials.
|
64
|
+
|
65
|
+
```ruby
|
66
|
+
S3Multipart.configure do |config|
|
67
|
+
config.bucket_name = '#########'
|
68
|
+
config.s3_access_key = '#########'
|
69
|
+
config.s3_secret_key = '#########'
|
70
|
+
end
|
71
|
+
```
|
72
|
+
|
73
|
+
## Getting Started
|
74
|
+
|
75
|
+
S3_Multipart comes with two helper functions required in integrating uploads into your application.
|
76
|
+
|
77
|
+
The `attach_uploader` function is available in your controllers. Call it from within a routed method, and pass in a block of code to be executed when the upload has completed successfully. The completed upload object has `location`, `upload_id`, `name`, and `key` attributes that can be accessed and manipulated.
|
78
|
+
|
79
|
+
```ruby
|
80
|
+
def your_controller_method
|
81
|
+
attach_uploader do |upload|
|
82
|
+
# your code here
|
83
|
+
end
|
84
|
+
end
|
85
|
+
```
|
86
|
+
|
87
|
+
The `multipart_uploader_form` function is a view helper, and generates the necessary input elements. It takes in a hash of allowed MIME types and a string of html to be interpolated between the generated file input element and submit button.
|
88
|
+
|
89
|
+
```ruby
|
90
|
+
<%= multipart_uploader_form(types: ['video/mpeg'],
|
91
|
+
input_name: 'uploader',
|
92
|
+
button_class: 'submit-button',
|
93
|
+
button_text: 'Upload selected videos',
|
94
|
+
html: %Q{<button class="upload-button">Select a Video</button>}) %>
|
95
|
+
```
|
96
|
+
|
97
|
+
puts out this:
|
98
|
+
|
99
|
+
```html
|
100
|
+
<input accept="video/mpeg" id="uploader" name="uploader" type="file">
|
101
|
+
<button class="submit-button">Upload selected videos</button>
|
102
|
+
```
|
103
|
+
|
104
|
+
## Contributing
|
105
|
+
|
106
|
+
S3_Multipart is very much a work in progress. If you squash a bug, make enhancemenets, or write more tests, please submit a pull request.
|
data/Rakefile
ADDED
File without changes
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module S3Multipart
|
2
|
+
class UploadsController < ApplicationController
|
3
|
+
def create
|
4
|
+
begin
|
5
|
+
response = Upload.initiate(params)
|
6
|
+
upload = Upload.create(key: response["key"], upload_id: response["upload_id"], name: response["name"])
|
7
|
+
response["id"] = upload["id"]
|
8
|
+
rescue
|
9
|
+
response = {error: 'There was an error initiating the upload'}
|
10
|
+
ensure
|
11
|
+
render :json => response
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def update
|
16
|
+
return complete_upload if params[:parts]
|
17
|
+
return sign_batch if params[:content_lengths]
|
18
|
+
return sign_part if params[:content_length]
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def sign_batch
|
24
|
+
begin
|
25
|
+
response = Upload.sign_batch(params)
|
26
|
+
rescue
|
27
|
+
response = {error: 'There was an error in processing your upload'}
|
28
|
+
ensure
|
29
|
+
render :json => response
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def sign_part
|
34
|
+
begin
|
35
|
+
response = Upload.sign_part(params)
|
36
|
+
rescue
|
37
|
+
response = {error: 'There was an error in processing your upload'}
|
38
|
+
ensure
|
39
|
+
render :json => response
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def complete_upload
|
44
|
+
begin
|
45
|
+
response = Upload.complete(params)
|
46
|
+
upload = Upload.find_by_upload_id(params[:upload_id])
|
47
|
+
upload.update_attributes(location: response[:location])
|
48
|
+
upload.on_complete
|
49
|
+
rescue
|
50
|
+
response = {error: 'There was an error completing the upload'}
|
51
|
+
ensure
|
52
|
+
render :json => response
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
data/config/routes.rb
ADDED
data/lib/s3_multipart.rb
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'active_record'
|
4
|
+
require 'xmlsimple'
|
5
|
+
require 'uuid'
|
6
|
+
|
7
|
+
module S3Multipart
|
8
|
+
|
9
|
+
class << self
|
10
|
+
|
11
|
+
# Syntax:
|
12
|
+
#
|
13
|
+
# S3_Multipart.configure do |config|
|
14
|
+
# config.s3_access_key = ''
|
15
|
+
# config.s3_secret_key = ''
|
16
|
+
# config.bucket_name = ''
|
17
|
+
# end
|
18
|
+
def configure(&block)
|
19
|
+
S3Multipart::Uploader::Config.configure(block)
|
20
|
+
end
|
21
|
+
|
22
|
+
def remove_unfinished_uploads(seconds=60*60*24*10)
|
23
|
+
# remove multipart uploads older than specified amt of seconds
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
module ActionControllerHelpers
|
29
|
+
|
30
|
+
#
|
31
|
+
# Stores a code block in the Upload class that will be executed (and passed the
|
32
|
+
# completed upload object) when the on_complete method is called on an
|
33
|
+
# instance of the Upload class
|
34
|
+
#
|
35
|
+
def attach_uploader(&block)
|
36
|
+
S3Multipart::Upload.class_eval do
|
37
|
+
self.on_complete_callback = block
|
38
|
+
def on_complete
|
39
|
+
Upload.on_complete_callback.call(self)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
require 's3_multipart/railtie'
|
49
|
+
require 's3_multipart/engine'
|
50
|
+
require 's3_multipart/http/net_http'
|
51
|
+
require 's3_multipart/uploader'
|
52
|
+
require 's3_multipart/uploader/config'
|
53
|
+
|
54
|
+
|
55
|
+
ActionController::Base.send(:include, S3Multipart::ActionControllerHelpers)
|